diff options
26 files changed, 247 insertions, 98 deletions
diff --git a/.github/workflows/lint_mypy.yml b/.github/workflows/lint_mypy.yml index 957e6c3..b76a751 100644 --- a/.github/workflows/lint_mypy.yml +++ b/.github/workflows/lint_mypy.yml @@ -30,4 +30,4 @@ jobs: with: python-version: '3.x' - run: python -m pip install mypy - - run: mypy --follow-imports=skip mesonbuild/mtest.py mesonbuild/minit.py mesonbuild/mintro.py mesonbuild/msetup.py mesonbuild/wrap tools/ mesonbuild/modules/fs.py mesonbuild/dependencies/mpi.py mesonbuild/dependencies/hdf5.py + - run: mypy --follow-imports=skip mesonbuild/mtest.py mesonbuild/minit.py mesonbuild/mintro.py mesonbuild/msetup.py mesonbuild/wrap tools/ mesonbuild/modules/fs.py mesonbuild/dependencies/mpi.py mesonbuild/dependencies/hdf5.py mesonbuild/compilers/mixins/intel.py diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md index 1c66d53..77e00bd 100644 --- a/docs/markdown/IDE-integration.md +++ b/docs/markdown/IDE-integration.md @@ -235,7 +235,7 @@ When these tests fail, the user probably wants to run the failing test in a debugger. To make this as integrated as possible, extract the tests from the `intro-tests.json` and `intro-benchmarks.json` files. This provides you with all the information needed to run the test: what command to execute, command -line arguments and environment variable settings. +line arguments, environment variable settings and how to process the output. ```json { @@ -244,6 +244,7 @@ line arguments and environment variable settings. "timeout": "the test timeout", "suite": ["list", "of", "test", "suites"], "is_parallel": true / false, + "protocol": "exitcode" / "tap", "cmd": ["command", "to", "run"], "env": { "VARIABLE1": "value 1", diff --git a/docs/markdown/snippets/introspect.md b/docs/markdown/snippets/introspect.md index 097fd17..9efa4d7 100644 --- a/docs/markdown/snippets/introspect.md +++ b/docs/markdown/snippets/introspect.md @@ -5,3 +5,7 @@ dependencies (--dependencies, intro-dependencies.json): scanning dependencies (--scan-dependencies): - added the `version` key containing the required dependency version + +tests and benchmarks (--tests, --benchmarks, intro-tests.json, +intro-benchmarks.json): +- added the `protocol` key diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 42948a0..aa48f7a 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -327,8 +327,6 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM """Intel "ICL" compiler abstraction.""" - __have_warned = False - def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, info: 'MachineInfo', exe_wrap, target, **kwargs): CCompiler.__init__(self, exelist, version, for_machine, is_cross, @@ -347,9 +345,7 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM args = [] std = options['c_std'] if std.value == 'c89': - if not self.__have_warned: - self.__have_warned = True - mlog.warning("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.") + mlog.warning("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.", once=True) elif std.value != 'none': args.append('/Qstd:' + std.value) return args diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index a2dd60f..f8ded00 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -486,7 +486,7 @@ class CPP11AsCPP14Mixin: # if one is using anything before that point, one cannot set the standard. if options['cpp_std'].value in {'vc++11', 'c++11'}: mlog.warning(self.id, 'does not support C++11;', - 'attempting best effort; setting the standard to C++14') + 'attempting best effort; setting the standard to C++14', once=True) # Don't mutate anything we're going to change, we need to use # deepcopy since we're messing with members, and we can't simply # copy the members because the option proxy doesn't support it. diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 6683486..dcca227 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -100,14 +100,15 @@ def gnulike_default_include_dirs(compiler: typing.Tuple[str], lang: str) -> typi p = subprocess.Popen( cmd, stdin=subprocess.DEVNULL, - stderr=subprocess.PIPE, + stderr=subprocess.STDOUT, stdout=subprocess.PIPE, env=env ) - stderr = p.stderr.read().decode('utf-8', errors='replace') + stdout = p.stdout.read().decode('utf-8', errors='replace') parse_state = 0 paths = [] - for line in stderr.split('\n'): + for line in stdout.split('\n'): + line = line.strip(' \n\r\t') if parse_state == 0: if line == '#include "..." search starts here:': parse_state = 1 @@ -115,14 +116,16 @@ def gnulike_default_include_dirs(compiler: typing.Tuple[str], lang: str) -> typi if line == '#include <...> search starts here:': parse_state = 2 else: - paths.append(line[1:]) + paths.append(line) elif parse_state == 2: if line == 'End of search list.': break else: - paths.append(line[1:]) + paths.append(line) if not paths: mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd))) + # Append a normalized copy of paths to make path lookup easier + paths += [os.path.normpath(x) for x in paths] return paths diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py index cf26a14..91edecd 100644 --- a/mesonbuild/compilers/mixins/intel.py +++ b/mesonbuild/compilers/mixins/intel.py @@ -41,26 +41,32 @@ if typing.TYPE_CHECKING: # https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-g # https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-traceback # https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html -clike_optimization_args = { - '0': ['-O0'], - 'g': ['-O0'], - '1': ['-O1'], - '2': ['-O2'], - '3': ['-O3'], - 's': ['-Os'], -} # type: typing.Dict[str, typing.List[str]] -# Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1, 19.0.0 class IntelGnuLikeCompiler(GnuLikeCompiler): + """ + Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1, 19.0 + debugoptimized: -g -O2 + release: -O3 + minsize: -O2 + """ BUILD_ARGS = { 'plain': [], - 'debug': ["-g", "-O0", "-traceback"], - 'debugoptimized': ["-g", "-O1", "-traceback"], - 'release': ["-O2"], - 'minsize': ["-Os"], + 'debug': ["-g", "-traceback"], + 'debugoptimized': ["-g", "-traceback"], + 'release': [], + 'minsize': [], 'custom': [], + } # type: typing.Dict[str, typing.List[str]] + + OPTIM_ARGS = { + '0': ['-O0'], + 'g': ['-O0'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Os'], } def __init__(self): @@ -75,9 +81,6 @@ class IntelGnuLikeCompiler(GnuLikeCompiler): self.id = 'intel' self.lang_header = 'none' - def get_optimization_args(self, optimization_level: str) -> typing.List[str]: - return clike_optimization_args[optimization_level] - def get_pch_suffix(self) -> str: return 'pchi' @@ -119,6 +122,9 @@ class IntelGnuLikeCompiler(GnuLikeCompiler): def get_buildtype_args(self, buildtype: str) -> typing.List[str]: return self.BUILD_ARGS[buildtype] + def get_optimization_args(self, optimization_level: str) -> typing.List[str]: + return self.OPTIM_ARGS[optimization_level] + class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler): @@ -126,11 +132,20 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler): BUILD_ARGS = { 'plain': [], - 'debug': ["/Zi", "/Od", "/traceback"], - 'debugoptimized': ["/Zi", "/O1", "/traceback"], - 'release': ["/O2"], - 'minsize': ["/Os"], + 'debug': ["/Zi", "/traceback"], + 'debugoptimized': ["/Zi", "/traceback"], + 'release': [], + 'minsize': [], 'custom': [], + } # type: typing.Dict[str, typing.List[str]] + + OPTIM_ARGS = { + '0': ['/O0'], + 'g': ['/O0'], + '1': ['/O1'], + '2': ['/O2'], + '3': ['/O3'], + 's': ['/Os'], } def __init__(self, target: str): @@ -168,3 +183,6 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler): def get_buildtype_args(self, buildtype: str) -> typing.List[str]: return self.BUILD_ARGS[buildtype] + + def get_optimization_args(self, optimization_level: str) -> typing.List[str]: + return self.OPTIM_ARGS[optimization_level] diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index b73e424..1ceb15f 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -33,14 +33,17 @@ class HDF5Dependency(ExternalDependency): # 1. pkg-config pkgconfig_files = ['hdf5', 'hdf5-serial'] # some distros put hdf5-1.2.3.pc with version number in .pc filename. - ret = subprocess.run(['pkg-config', '--list-all'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, - universal_newlines=True) - if ret.returncode == 0: - for pkg in ret.stdout.split('\n'): - if pkg.startswith(('hdf5')): - pkgconfig_files.append(pkg.split(' ', 1)[0]) - pkgconfig_files = list(set(pkgconfig_files)) # dedupe - + try: + ret = subprocess.run(['pkg-config', '--list-all'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, + universal_newlines=True) + if ret.returncode == 0: + for pkg in ret.stdout.split('\n'): + if pkg.startswith(('hdf5')): + pkgconfig_files.append(pkg.split(' ', 1)[0]) + pkgconfig_files = list(set(pkgconfig_files)) # dedupe + except FileNotFoundError: + # pkg-config was not available + pass if language not in ('c', 'cpp', 'fortran'): raise DependencyException('Language {} is not supported with HDF5.'.format(language)) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 1c9c542..ff9f1d9 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -302,6 +302,7 @@ def get_test_list(testdata) -> List[Dict[str, Union[str, int, List[str], Dict[st to['suite'] = t.suite to['is_parallel'] = t.is_parallel to['priority'] = t.priority + to['protocol'] = t.protocol result.append(to) return result diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index c779a58..a145cc1 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -18,7 +18,18 @@ import sys import time import platform from contextlib import contextmanager -from typing import Any, Generator, List, Optional, Sequence, TextIO, Union, cast +from typing import ( + Any, + Generator, + List, + Optional, + Sequence, + Set, + TextIO, + Tuple, + Union, + cast, +) from pathlib import Path """This is (mostly) a standalone module used to write logging @@ -56,6 +67,7 @@ log_fatal_warnings = False # type: bool log_disable_stdout = False # type: bool log_errors_only = False # type: bool _in_ci = 'CI' in os.environ # type: bool +_logged_once = set() # type: Set[Tuple[str, ...]] def disable() -> None: global log_disable_stdout @@ -160,7 +172,6 @@ def process_markup(args: Sequence[Union[AnsiDecorator, str]], keep: bool) -> Lis return arr def force_print(*args: str, **kwargs: Any) -> None: - global log_disable_stdout if log_disable_stdout: return iostr = io.StringIO() @@ -197,7 +208,6 @@ def cmd_ci_include(file: str) -> None: def log(*args: Union[str, AnsiDecorator], is_error: bool = False, **kwargs: Any) -> None: - global log_errors_only arr = process_markup(args, False) if log_file is not None: print(*arr, file=log_file, **kwargs) @@ -207,7 +217,21 @@ def log(*args: Union[str, AnsiDecorator], is_error: bool = False, if not log_errors_only or is_error: force_print(*arr, **kwargs) -def _log_error(severity: str, *rargs: Union[str, AnsiDecorator], **kwargs: Any) -> None: +def log_once(*args: Union[str, AnsiDecorator], is_error: bool = False, + **kwargs: Any) -> None: + """Log variant that only prints a given message one time per meson invocation. + + This considers nasi decorated values by the values they wrap without + regard for the AnsiDecorator itself. + """ + t = tuple(a.text if isinstance(a, AnsiDecorator) else a for a in args) + if t in _logged_once: + return + _logged_once.add(t) + log(*args, is_error=is_error, **kwargs) + +def _log_error(severity: str, *rargs: Union[str, AnsiDecorator], + once: bool = False, **kwargs: Any) -> None: from .mesonlib import get_error_location_string from .environment import build_filename from .mesonlib import MesonException @@ -234,20 +258,22 @@ def _log_error(severity: str, *rargs: Union[str, AnsiDecorator], **kwargs: Any) location_list = cast(List[Union[str, AnsiDecorator]], [location_str]) args = location_list + args - log(*args, **kwargs) + if once: + log_once(*args, **kwargs) + else: + log(*args, **kwargs) - global log_fatal_warnings if log_fatal_warnings: raise MesonException("Fatal warnings enabled, aborting") -def error(*args: Union[str, AnsiDecorator], **kwargs: Any) -> None: - return _log_error('error', *args, **kwargs, is_error=True) +def error(*args: Union[str, AnsiDecorator], once: bool = False, **kwargs: Any) -> None: + return _log_error('error', *args, **kwargs, is_error=True, once=once) -def warning(*args: Union[str, AnsiDecorator], **kwargs: Any) -> None: - return _log_error('warning', *args, **kwargs, is_error=True) +def warning(*args: Union[str, AnsiDecorator], once: bool = False, **kwargs: Any) -> None: + return _log_error('warning', *args, **kwargs, is_error=True, once=once) -def deprecation(*args: Union[str, AnsiDecorator], **kwargs: Any) -> None: - return _log_error('deprecation', *args, **kwargs, is_error=True) +def deprecation(*args: Union[str, AnsiDecorator], once: bool = False, **kwargs: Any) -> None: + return _log_error('deprecation', *args, **kwargs, is_error=True, once=once) def get_relative_path(target: Path, current: Path) -> Path: """Get the path to target from current""" diff --git a/msi/createmsi.py b/msi/createmsi.py index 9b4e105..f80d1dc 100644 --- a/msi/createmsi.py +++ b/msi/createmsi.py @@ -13,8 +13,15 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - -import sys, os, subprocess, shutil, uuid +''' + This script is for generating MSI packages + for Windows users. +''' +import subprocess +import shutil +import uuid +import sys +import os from glob import glob import platform import xml.etree.ElementTree as ET @@ -23,27 +30,53 @@ sys.path.append(os.getcwd()) from mesonbuild import coredata def gen_guid(): + ''' + Generate guid + ''' return str(uuid.uuid4()).upper() class Node: + ''' + Node to hold path and directory values + ''' + def __init__(self, dirs, files): - assert(isinstance(dirs, list)) - assert(isinstance(files, list)) + self.check_dirs(dirs) + self.check_files(files) self.dirs = dirs self.files = files + @staticmethod + def check_dirs(dirs): + ''' + Check to see if directory is instance of list + ''' + assert isinstance(dirs, list) + + @staticmethod + def check_files(files): + ''' + Check to see if files is instance of list + ''' + assert isinstance(files, list) + + class PackageGenerator: + ''' + Package generator for MSI pacakges + ''' def __init__(self): self.product_name = 'Meson Build System' self.manufacturer = 'The Meson Development Team' self.version = coredata.version.replace('dev', '') + self.root = None self.guid = '*' self.update_guid = '141527EE-E28A-4D14-97A4-92E6075D28B2' self.main_xml = 'meson.wxs' self.main_o = 'meson.wixobj' self.bytesize = 32 if '32' in platform.architecture()[0] else 64 - self.final_output = 'meson-%s-%d.msi' % (self.version, self.bytesize) + self.final_output = 'meson-{}-{}.msi'.format(self.version, self.bytesize) self.staging_dirs = ['dist', 'dist2'] if self.bytesize == 64: self.progfile_dir = 'ProgramFiles64Folder' @@ -72,18 +105,27 @@ class PackageGenerator: } } self.feature_components = {} - for sd in self.staging_dirs: - self.feature_components[sd] = [] + for s_d in self.staging_dirs: + self.feature_components[s_d] = [] - def get_all_modules_from_dir(self, dirname): + @staticmethod + def get_all_modules_from_dir(dirname): + ''' + Get all modules required for Meson build MSI package + from directories. + ''' modname = os.path.basename(dirname) modules = [os.path.splitext(os.path.split(x)[1])[0] for x in glob(os.path.join(dirname, '*'))] modules = ['mesonbuild.' + modname + '.' + x for x in modules if not x.startswith('_')] return modules - def get_more_modules(self): - # Python packagers want to minimal and only copy the things that - # they can see that are used. They are blind to many things. + @staticmethod + def get_more_modules(): + ''' + Getter for missing Modules. + Python packagers want to be minimal and only copy the things + that they can see that being used. They are blind to many things. + ''' return ['distutils.archive_util', 'distutils.cmd', 'distutils.config', @@ -104,6 +146,9 @@ class PackageGenerator: ] def build_dist(self): + ''' + Build dist file from PyInstaller info + ''' for sdir in self.staging_dirs: if os.path.exists(sdir): shutil.rmtree(sdir) @@ -137,6 +182,9 @@ class PackageGenerator: sys.exit('Ninja exe missing from staging dir.') def generate_files(self): + ''' + Generate package files for MSI installer package + ''' self.root = ET.Element('Wix', {'xmlns': 'http://schemas.microsoft.com/wix/2006/wi'}) product = ET.SubElement(self.root, 'Product', { 'Name': self.product_name, @@ -148,10 +196,10 @@ class PackageGenerator: 'Version': self.version, }) - package = ET.SubElement(product, 'Package', { + package = ET.SubElement(product, 'Package', { 'Id': '*', 'Keywords': 'Installer', - 'Description': 'Meson %s installer' % self.version, + 'Description': 'Meson {} installer'.format(self.version), 'Comments': 'Meson is a high performance build system', 'Manufacturer': 'The Meson Development Team', 'InstallerVersion': '500', @@ -195,8 +243,8 @@ class PackageGenerator: ET.SubElement(product, 'UIRef', { 'Id': 'WixUI_FeatureTree', }) - for sd in self.staging_dirs: - assert(os.path.isdir(sd)) + for s_d in self.staging_dirs: + assert os.path.isdir(s_d) top_feature = ET.SubElement(product, 'Feature', { 'Id': 'Complete', 'Title': 'Meson ' + self.version, @@ -205,13 +253,13 @@ class PackageGenerator: 'Level': '1', 'ConfigurableDirectory': 'INSTALLDIR', }) - for sd in self.staging_dirs: + for s_d in self.staging_dirs: nodes = {} - for root, dirs, files in os.walk(sd): + for root, dirs, files in os.walk(s_d): cur_node = Node(dirs, files) nodes[root] = cur_node - self.create_xml(nodes, sd, installdir, sd) - self.build_features(nodes, top_feature, sd) + self.create_xml(nodes, s_d, installdir, s_d) + self.build_features(top_feature, s_d) vcredist_feature = ET.SubElement(top_feature, 'Feature', { 'Id': 'VCRedist', 'Title': 'Visual C++ runtime', @@ -224,20 +272,26 @@ class PackageGenerator: # ElementTree can not do prettyprinting so do it manually import xml.dom.minidom doc = xml.dom.minidom.parse(self.main_xml) - with open(self.main_xml, 'w') as of: - of.write(doc.toprettyxml()) + with open(self.main_xml, 'w') as open_file: + open_file.write(doc.toprettyxml()) - def build_features(self, nodes, top_feature, staging_dir): - feature = ET.SubElement(top_feature, 'Feature', self.feature_properties[staging_dir]) + def build_features(self, top_feature, staging_dir): + ''' + Generate build features + ''' + feature = ET.SubElement(top_feature, 'Feature', self.feature_properties[staging_dir]) for component_id in self.feature_components[staging_dir]: ET.SubElement(feature, 'ComponentRef', { 'Id': component_id, }) def create_xml(self, nodes, current_dir, parent_xml_node, staging_dir): + ''' + Create XML file + ''' cur_node = nodes[current_dir] if cur_node.files: - component_id = 'ApplicationFiles%d' % self.component_num + component_id = 'ApplicationFiles{}'.format(self.component_num) comp_xml_node = ET.SubElement(parent_xml_node, 'Component', { 'Id': component_id, 'Guid': gen_guid(), @@ -255,12 +309,12 @@ class PackageGenerator: 'Value': '[INSTALLDIR]', }) self.component_num += 1 - for f in cur_node.files: - file_id = os.path.join(current_dir, f).replace('\\', '_').replace('#', '_').replace('-', '_') + for f_node in cur_node.files: + file_id = os.path.join(current_dir, f_node).replace('\\', '_').replace('#', '_').replace('-', '_') ET.SubElement(comp_xml_node, 'File', { 'Id': file_id, - 'Name': f, - 'Source': os.path.join(current_dir, f), + 'Name': f_node, + 'Source': os.path.join(current_dir, f_node), }) for dirname in cur_node.dirs: @@ -272,6 +326,9 @@ class PackageGenerator: self.create_xml(nodes, os.path.join(current_dir, dirname), dir_node, staging_dir) def build_package(self): + ''' + Generate the Meson build MSI package. + ''' wixdir = 'c:\\Program Files\\Wix Toolset v3.11\\bin' if not os.path.isdir(wixdir): wixdir = 'c:\\Program Files (x86)\\Wix Toolset v3.11\\bin' diff --git a/run_tests.py b/run_tests.py index 33dc1be..c811705 100755 --- a/run_tests.py +++ b/run_tests.py @@ -211,7 +211,7 @@ def get_backend_commands(backend, debug=False): if v == '1.9': NINJA_1_9_OR_NEWER = True else: - print('Found ninja <1.9, tests will run slower') + mlog.warning('Found ninja <1.9, tests will run slower', once=True) if 'CI' in os.environ: raise RuntimeError('Require ninja >= 1.9 when running on Meson CI') break @@ -238,12 +238,12 @@ def ensure_backend_detects_changes(backend): # XXX: Upgrade Travis image to Apple FS when that becomes available # TODO: Detect HFS+ vs APFS if mesonlib.is_osx(): - print('Running on HFS+, enabling timestamp resolution workaround') + mlog.warning('Running on HFS+, enabling timestamp resolution workaround', once=True) need_workaround = True # We're using ninja >= 1.9 which has QuLogic's patch for sub-1s resolution # timestamps if not NINJA_1_9_OR_NEWER: - print('Don\'t have ninja >= 1.9, enabling timestamp resolution workaround') + mlog.warning('Don\'t have ninja >= 1.9, enabling timestamp resolution workaround', once=True) need_workaround = True # Increase the difference between build.ninja's timestamp and the timestamp # of whatever you changed: https://github.com/ninja-build/ninja/issues/371 diff --git a/run_unittests.py b/run_unittests.py index a7a0d26..977a4f8 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1141,6 +1141,35 @@ class InternalTests(unittest.TestCase): deps = d.get_all_dependencies(target) self.assertEqual(deps, expdeps) + def test_log_once(self): + f = io.StringIO() + with mock.patch('mesonbuild.mlog.log_file', f), \ + mock.patch('mesonbuild.mlog._logged_once', set()): + mesonbuild.mlog.log_once('foo') + mesonbuild.mlog.log_once('foo') + actual = f.getvalue().strip() + self.assertEqual(actual, 'foo', actual) + + def test_log_once_ansi(self): + f = io.StringIO() + with mock.patch('mesonbuild.mlog.log_file', f), \ + mock.patch('mesonbuild.mlog._logged_once', set()): + mesonbuild.mlog.log_once(mesonbuild.mlog.bold('foo')) + mesonbuild.mlog.log_once(mesonbuild.mlog.bold('foo')) + actual = f.getvalue().strip() + self.assertEqual(actual.count('foo'), 1, actual) + + mesonbuild.mlog.log_once('foo') + actual = f.getvalue().strip() + self.assertEqual(actual.count('foo'), 1, actual) + + f.truncate() + + mesonbuild.mlog.warning('bar', once=True) + mesonbuild.mlog.warning('bar', once=True) + actual = f.getvalue().strip() + self.assertEqual(actual.count('bar'), 1, actual) + @unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release') class DataTests(unittest.TestCase): @@ -2620,7 +2649,6 @@ int main(int argc, char **argv) { 'disttest-1.4.3/subprojects/vcssub/meson.build']), sorted(z.namelist())) - def test_rpath_uses_ORIGIN(self): ''' Test that built targets use $ORIGIN in rpath, which ensures that they @@ -3813,6 +3841,7 @@ recommended as it is not supported on some platforms''') ('timeout', int), ('suite', list), ('is_parallel', bool), + ('protocol', str), ] buildoptions_keylist = [ diff --git a/test cases/cmake/5 object library/main.cpp b/test cases/cmake/5 object library/main.cpp index 918f332..cdf54f1 100644 --- a/test cases/cmake/5 object library/main.cpp +++ b/test cases/cmake/5 object library/main.cpp @@ -6,4 +6,5 @@ using namespace std; int main(void) { cout << getLibStr() << " -- " << getZlibVers() << endl; + return EXIT_SUCCESS; } diff --git a/test cases/cmake/5 object library/meson.build b/test cases/cmake/5 object library/meson.build index 268c2be..c338136 100644 --- a/test cases/cmake/5 object library/meson.build +++ b/test cases/cmake/5 object library/meson.build @@ -1,12 +1,13 @@ -project('cmake_object_lib_test', ['c', 'cpp']) +project('cmake_object_lib_test', 'cpp') dep_test = dependency('ZLIB', method: 'cmake', required: false) if not dep_test.found() error('MESON_SKIP_TEST: zlib is not installed') endif -if build_machine.system() == 'windows' - error('MESON_SKIP_TEST: Windows is not supported because of symbol export problems') +cpp = meson.get_compiler('cpp') +if build_machine.system() == 'windows' and cpp.get_id() != 'gcc' + error('MESON_SKIP_TEST: Windows link.exe is not supported because of symbol export problems') endif cm = import('cmake') diff --git a/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt b/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt index a47fa59..062496e 100644 --- a/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt +++ b/test cases/cmake/5 object library/subprojects/cmObjLib/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.7) -project(cmObject) +project(cmObject CXX) find_package(ZLIB REQUIRED) diff --git a/test cases/cmake/5 object library/subprojects/cmObjLib/libA.cpp b/test cases/cmake/5 object library/subprojects/cmObjLib/libA.cpp index 3736b2c..1d579cf 100644 --- a/test cases/cmake/5 object library/subprojects/cmObjLib/libA.cpp +++ b/test cases/cmake/5 object library/subprojects/cmObjLib/libA.cpp @@ -1,5 +1,5 @@ #include "libA.hpp" -std::string getLibStr() { +std::string getLibStr(void) { return "Hello World"; } diff --git a/test cases/cmake/5 object library/subprojects/cmObjLib/libB.cpp b/test cases/cmake/5 object library/subprojects/cmObjLib/libB.cpp index b359c29..22fe7c2 100644 --- a/test cases/cmake/5 object library/subprojects/cmObjLib/libB.cpp +++ b/test cases/cmake/5 object library/subprojects/cmObjLib/libB.cpp @@ -1,6 +1,6 @@ #include "libB.hpp" #include <zlib.h> -std::string getZlibVers() { +std::string getZlibVers(void) { return zlibVersion(); } diff --git a/test cases/cmake/6 object library no dep/main.cpp b/test cases/cmake/6 object library no dep/main.cpp index 918f332..cdf54f1 100644 --- a/test cases/cmake/6 object library no dep/main.cpp +++ b/test cases/cmake/6 object library no dep/main.cpp @@ -6,4 +6,5 @@ using namespace std; int main(void) { cout << getLibStr() << " -- " << getZlibVers() << endl; + return EXIT_SUCCESS; } diff --git a/test cases/cmake/6 object library no dep/meson.build b/test cases/cmake/6 object library no dep/meson.build index 7494fee..b2c66ed 100644 --- a/test cases/cmake/6 object library no dep/meson.build +++ b/test cases/cmake/6 object library no dep/meson.build @@ -1,7 +1,8 @@ -project('cmake_object_lib_test', ['c', 'cpp']) +project('cmake_object_lib_test', 'cpp') -if build_machine.system() == 'windows' - error('MESON_SKIP_TEST: Windows is not supported because of symbol export problems') +cpp = meson.get_compiler('cpp') +if build_machine.system() == 'windows' and cpp.get_id() != 'gcc' + error('MESON_SKIP_TEST: Windows link.exe is not supported because of symbol export problems') endif cm = import('cmake') diff --git a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt index 5e0b0b1..9e136af 100644 --- a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt +++ b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.7) -project(cmObject) +project(cmObject CXX) add_library(lib_obj OBJECT libA.cpp libB.cpp) add_library(lib_sha SHARED $<TARGET_OBJECTS:lib_obj>) diff --git a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libA.cpp b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libA.cpp index 3736b2c..1d579cf 100644 --- a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libA.cpp +++ b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libA.cpp @@ -1,5 +1,5 @@ #include "libA.hpp" -std::string getLibStr() { +std::string getLibStr(void) { return "Hello World"; } diff --git a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.cpp b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.cpp index 187d10f..aa44816 100644 --- a/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.cpp +++ b/test cases/cmake/6 object library no dep/subprojects/cmObjLib/libB.cpp @@ -1,5 +1,5 @@ #include "libB.hpp" -std::string getZlibVers() { +std::string getZlibVers(void) { return "STUB"; } diff --git a/test cases/fortran/20 buildtype/main.f90 b/test cases/fortran/20 buildtype/main.f90 new file mode 100644 index 0000000..1e16cbc --- /dev/null +++ b/test cases/fortran/20 buildtype/main.f90 @@ -0,0 +1 @@ +end program diff --git a/test cases/fortran/20 buildtype/meson.build b/test cases/fortran/20 buildtype/meson.build new file mode 100644 index 0000000..2be6337 --- /dev/null +++ b/test cases/fortran/20 buildtype/meson.build @@ -0,0 +1,5 @@ +# checks for unexpected behavior on non-default buildtype and warning_level +project('build type Fortran', 'fortran', + default_options: ['buildtype=release', 'warning_level=3']) + +executable('main', 'main.f90') diff --git a/test cases/osx/2 library versions/meson.build b/test cases/osx/2 library versions/meson.build index 0d21a3a..5420133 100644 --- a/test cases/osx/2 library versions/meson.build +++ b/test cases/osx/2 library versions/meson.build @@ -8,10 +8,11 @@ endif zlib_dep = dependency('zlib', required: required) if zlib_dep.found() + build_rpath = zlib_dep.type_name() == 'pkgconfig' ? zlib_dep.get_pkgconfig_variable('libdir') : 'lib' some = shared_library('some', 'lib.c', # duplicate the rpath again, in order # to test Meson's RPATH deduplication - build_rpath : zlib_dep.get_pkgconfig_variable('libdir'), + build_rpath : build_rpath, dependencies : zlib_dep, version : '1.2.3', soversion : '7', |