diff options
-rw-r--r-- | .editorconfig | 1 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 8 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/clang.py | 2 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 6 | ||||
-rw-r--r-- | mesonbuild/interpreter/dependencyfallbacks.py | 24 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 6 | ||||
-rw-r--r-- | mesonbuild/mtest.py | 9 | ||||
-rw-r--r-- | mesonbuild/programs.py | 3 | ||||
-rwxr-xr-x | run_unittests.py | 3 | ||||
-rw-r--r-- | test cases/common/98 subproject subdir/meson.build | 2 | ||||
-rw-r--r-- | test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build | 2 | ||||
-rw-r--r-- | test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt | 1 | ||||
-rwxr-xr-x | test cases/unit/99 relative find program/foo.py | 3 | ||||
-rw-r--r-- | test cases/unit/99 relative find program/meson.build | 3 | ||||
-rw-r--r-- | test cases/unit/99 relative find program/subdir/meson.build | 2 | ||||
-rw-r--r-- | unittests/allplatformstests.py | 28 | ||||
-rw-r--r-- | unittests/internaltests.py | 16 | ||||
-rw-r--r-- | unittests/platformagnostictests.py | 34 |
18 files changed, 106 insertions, 47 deletions
diff --git a/.editorconfig b/.editorconfig index 6401c25..827d6f3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,6 +5,7 @@ charset = utf-8 end_of_line = lf indent_style = space trim_trailing_whitespace = true +insert_final_newline = true [*.[ch]] indent_size = 4 diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index d821734..844c612 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -515,7 +515,13 @@ class NinjaBackend(backends.Backend): ninja = environment.detect_ninja_command_and_version(log=True) if need_setup_vsenv: builddir = Path(self.environment.get_build_dir()) - builddir = builddir.relative_to(Path.cwd()) + try: + # For prettier printing, reduce to a relative path. If + # impossible (e.g., because builddir and cwd are on + # different Windows drives), skip and use the full path. + builddir = builddir.relative_to(Path.cwd()) + except ValueError: + pass meson_command = mesonlib.join_args(mesonlib.get_meson_command()) mlog.log() mlog.log('Visual Studio environment is needed to run Ninja. It is recommended to use Meson wrapper:') diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index f7e9492..133ce96 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -40,7 +40,7 @@ clang_optimization_args = { '1': ['-O1'], '2': ['-O2'], '3': ['-O3'], - 's': ['-Os'], + 's': ['-Oz'], } # type: T.Dict[str, T.List[str]] class ClangCompiler(GnuLikeCompiler): diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 20a4ccb..3abba6d 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -43,6 +43,7 @@ if T.TYPE_CHECKING: KeyedOptionDictType = T.Union[T.Dict['OptionKey', 'UserOption[T.Any]'], OptionOverrideProxy] CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], str] +# Check major_versions_differ() if changing versioning scheme. version = '0.59.99' backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'xcode'] @@ -990,7 +991,10 @@ def format_cmd_line_options(options: argparse.Namespace) -> str: return ' '.join([shlex.quote(x) for x in cmdline]) def major_versions_differ(v1: str, v2: str) -> bool: - return v1.split('.')[0:2] != v2.split('.')[0:2] + v1_major, v1_minor = v1.rsplit('.', 1) + v2_major, v2_minor = v2.rsplit('.', 1) + # Major version differ, or one is development version but not the other. + return v1_major != v2_major or ('99' in {v1_minor, v2_minor} and v1_minor != v2_minor) def load(build_dir: str) -> CoreData: filename = os.path.join(build_dir, 'meson-private', 'coredata.dat') diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py index 2a4f212..7d3a7d8 100644 --- a/mesonbuild/interpreter/dependencyfallbacks.py +++ b/mesonbuild/interpreter/dependencyfallbacks.py @@ -16,7 +16,8 @@ if T.TYPE_CHECKING: class DependencyFallbacksHolder(MesonInterpreterObject): - def __init__(self, interpreter: 'Interpreter', names: T.List[str], allow_fallback: T.Optional[bool] = None) -> None: + def __init__(self, interpreter: 'Interpreter', names: T.List[str], allow_fallback: T.Optional[bool] = None, + default_options: T.Optional[T.List[str]] = None) -> None: super().__init__(subproject=interpreter.subproject) self.interpreter = interpreter self.subproject = interpreter.subproject @@ -27,7 +28,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject): self.allow_fallback = allow_fallback self.subproject_name = None self.subproject_varname = None - self.subproject_kwargs = None + self.subproject_kwargs = {'default_options': default_options or []} self.names: T.List[str] = [] for name in names: if not name: @@ -39,12 +40,9 @@ class DependencyFallbacksHolder(MesonInterpreterObject): raise InterpreterException('dependency_fallbacks name {name!r} is duplicated') self.names.append(name) - def set_fallback(self, fbinfo: T.Optional[T.Union[T.List[str], str]], default_options: T.Optional[T.List[str]] = None) -> None: - # Legacy: This converts dependency()'s fallback and default_options kwargs. + def set_fallback(self, fbinfo: T.Optional[T.Union[T.List[str], str]]) -> None: + # Legacy: This converts dependency()'s fallback kwargs. if fbinfo is None: - if default_options is not None: - mlog.warning('The "default_options" keyword argument does nothing without a fallback subproject.', - location=self.interpreter.current_node) return if self.allow_fallback is not None: raise InvalidArguments('"fallback" and "allow_fallback" arguments are mutually exclusive') @@ -60,10 +58,9 @@ class DependencyFallbacksHolder(MesonInterpreterObject): subp_name, varname = fbinfo else: raise InterpreterException('Fallback info must have one or two items.') - kwargs = {'default_options': default_options or []} - self._subproject_impl(subp_name, varname, kwargs) + self._subproject_impl(subp_name, varname) - def _subproject_impl(self, subp_name: str, varname: str, kwargs: TYPE_nkwargs) -> None: + def _subproject_impl(self, subp_name: str, varname: str) -> None: if not varname: # If no variable name is specified, check if the wrap file has one. # If the wrap file has a variable name, better use it because the @@ -75,7 +72,6 @@ class DependencyFallbacksHolder(MesonInterpreterObject): assert self.subproject_name is None self.subproject_name = subp_name self.subproject_varname = varname - self.subproject_kwargs = kwargs def _do_dependency_cache(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: name = func_args[0] @@ -223,6 +219,10 @@ class DependencyFallbacksHolder(MesonInterpreterObject): if cached_dep: found_vers = cached_dep.get_version() if not self._check_version(wanted_vers, found_vers): + if not override: + # We cached this dependency on disk from a previous run, + # but it could got updated on the system in the meantime. + return None mlog.log('Dependency', mlog.bold(name), 'found:', mlog.red('NO'), 'found', mlog.normal_cyan(found_vers), 'but need:', @@ -329,7 +329,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject): if subp_name: self.forcefallback |= subp_name in force_fallback_for if self.forcefallback or self.allow_fallback is True or required or self._get_subproject(subp_name): - self._subproject_impl(subp_name, varname, {}) + self._subproject_impl(subp_name, varname) break candidates = self._get_candidates() diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 891c606..4d4e5da 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1472,8 +1472,8 @@ external dependencies (including libraries) must go to "dependencies".''') raise InvalidArguments('"allow_fallback" argument must be boolean') fallback = kwargs.get('fallback') default_options = kwargs.get('default_options') - df = DependencyFallbacksHolder(self, names, allow_fallback) - df.set_fallback(fallback, default_options) + df = DependencyFallbacksHolder(self, names, allow_fallback, default_options) + df.set_fallback(fallback) not_found_message = kwargs.get('not_found_message', '') if not isinstance(not_found_message, str): raise InvalidArguments('The not_found_message must be a string.') @@ -2322,7 +2322,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self # https://github.com/mesonbuild/meson/issues/3275#issuecomment-641354956 # https://github.com/mesonbuild/meson/issues/3742 warnargs = ('/W1', '/W2', '/W3', '/W4', '/Wall', '-Wall', '-Wextra') - optargs = ('-O0', '-O2', '-O3', '-Os', '/O1', '/O2', '/Os') + optargs = ('-O0', '-O2', '-O3', '-Os', '-Oz', '/O1', '/O2', '/Os') for arg in args: if arg in warnargs: mlog.warning(f'Consider using the built-in warning_level option instead of using "{arg}".', diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 4c1d00e..fd175ba 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -990,7 +990,14 @@ class TestRunGTest(TestRunExitCode): if self.test.workdir: filename = os.path.join(self.test.workdir, filename) - self.junit = et.parse(filename) + try: + self.junit = et.parse(filename) + except FileNotFoundError: + # This can happen if the test fails to run or complete for some + # reason, like the rpath for libgtest isn't properly set. ExitCode + # will handle the failure, don't generate a stacktrace. + pass + super().complete(returncode, res, stdo, stde) TestRun.PROTOCOL_TO_CLASS[TestProtocol.GTEST] = TestRunGTest diff --git a/mesonbuild/programs.py b/mesonbuild/programs.py index ffd177f..af27801 100644 --- a/mesonbuild/programs.py +++ b/mesonbuild/programs.py @@ -295,6 +295,9 @@ class ExternalProgram(mesonlib.HoldableObject): commands = self._search_dir(name, search_dir) if commands: return commands + # If there is a directory component, do not look in PATH + if os.path.dirname(name) and not os.path.isabs(name): + return [None] # Do a standard search in PATH path = os.environ.get('PATH', None) if mesonlib.is_windows() and path: diff --git a/run_unittests.py b/run_unittests.py index 2421e8d..f438daa 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -54,6 +54,7 @@ from unittests.linuxliketests import LinuxlikeTests from unittests.pythontests import PythonTests from unittests.subprojectscommandtests import SubprojectsCommandTests from unittests.windowstests import WindowsTests +from unittests.platformagnostictests import PlatformAgnosticTests def unset_envs(): # For unit tests we must fully control all command lines @@ -120,7 +121,7 @@ def main(): setup_backend() cases = ['InternalTests', 'DataTests', 'AllPlatformTests', 'FailureTests', 'PythonTests', 'NativeFileTests', 'RewriterTests', 'CrossFileTests', - 'TAPParserTests', 'SubprojectsCommandTests', + 'TAPParserTests', 'SubprojectsCommandTests', 'PlatformAgnosticTests', 'LinuxlikeTests', 'LinuxCrossArmTests', 'LinuxCrossMingwTests', 'WindowsTests', 'DarwinTests'] diff --git a/test cases/common/98 subproject subdir/meson.build b/test cases/common/98 subproject subdir/meson.build index 95bf34e..3053b3b 100644 --- a/test cases/common/98 subproject subdir/meson.build +++ b/test cases/common/98 subproject subdir/meson.build @@ -27,7 +27,7 @@ d = dependency('sub-notfound', fallback : 'sub_novar', required : false) assert(not d.found(), 'Dependency should be not-found') # Verify that implicit fallback works because subprojects/sub_implicit directory exists -d = dependency('sub_implicit') +d = dependency('sub_implicit', default_options: 'opt=overriden') assert(d.found(), 'Should implicitly fallback') # Verify that implicit fallback works because sub_implicit.wrap has diff --git a/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build b/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build index a1c46a1..9f43604 100644 --- a/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build +++ b/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build @@ -9,3 +9,5 @@ sub_implicit_provide2_dep = dep # This one is not overridden but the wrap file tells the variable name to use. glib_dep = dep + +assert(get_option('opt') == 'overriden')
\ No newline at end of file diff --git a/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt b/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt new file mode 100644 index 0000000..770178c --- /dev/null +++ b/test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt @@ -0,0 +1 @@ +option('opt', type: 'string', value: 'default')
\ No newline at end of file diff --git a/test cases/unit/99 relative find program/foo.py b/test cases/unit/99 relative find program/foo.py new file mode 100755 index 0000000..21239b7 --- /dev/null +++ b/test cases/unit/99 relative find program/foo.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +exit(0)
\ No newline at end of file diff --git a/test cases/unit/99 relative find program/meson.build b/test cases/unit/99 relative find program/meson.build new file mode 100644 index 0000000..5745d8a --- /dev/null +++ b/test cases/unit/99 relative find program/meson.build @@ -0,0 +1,3 @@ +project('relative find program') + +subdir('subdir')
\ No newline at end of file diff --git a/test cases/unit/99 relative find program/subdir/meson.build b/test cases/unit/99 relative find program/subdir/meson.build new file mode 100644 index 0000000..475f5f5 --- /dev/null +++ b/test cases/unit/99 relative find program/subdir/meson.build @@ -0,0 +1,2 @@ +prog = find_program('./foo.py', required: false) +assert(not prog.found())
\ No newline at end of file diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 524f0d0..7afa989 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2356,16 +2356,12 @@ class AllPlatformTests(BasePlatformTests): self.wipe() self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env) - def __reconfigure(self, change_minor=False): + def __reconfigure(self): # Set an older version to force a reconfigure from scratch filename = os.path.join(self.privatedir, 'coredata.dat') with open(filename, 'rb') as f: obj = pickle.load(f) - if change_minor: - v = mesonbuild.coredata.version.split('.') - obj.version = '.'.join(v[0:2] + [str(int(v[2]) + 1)]) - else: - obj.version = '0.47.0' + obj.version = '0.47.0' with open(filename, 'wb') as f: pickle.dump(obj, f) @@ -2405,25 +2401,7 @@ class AllPlatformTests(BasePlatformTests): testdir = os.path.join(self.common_test_dir, '157 custom target subdir depend files') self.init(testdir) self.__reconfigure() - - with Path(self.builddir): - self.init(testdir, extra_args=['--wipe']) - - def test_minor_version_does_not_reconfigure_wipe(self): - testdir = os.path.join(self.unit_test_dir, '48 reconfigure') - self.init(testdir, extra_args=['-Dopt1=val1']) - self.setconf('-Dopt2=val2') - - self.__reconfigure(change_minor=True) - - out = self.init(testdir, extra_args=['--reconfigure', '-Dopt3=val3']) - self.assertNotRegex(out, 'Regenerating configuration from scratch') - self.assertRegex(out, 'opt1 val1') - self.assertRegex(out, 'opt2 val2') - self.assertRegex(out, 'opt3 val3') - self.assertRegex(out, 'opt4 default4') - self.build() - self.run_tests() + self.init(testdir, extra_args=['--wipe'], workdir=self.builddir) def test_target_construct_id_from_path(self): # This id is stable but not guessable. diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 8cebeb8..a6f1ca5 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -34,8 +34,8 @@ import mesonbuild.dependencies.factory import mesonbuild.compilers import mesonbuild.envconfig import mesonbuild.environment -import mesonbuild.coredata import mesonbuild.modules.gnome +from mesonbuild import coredata from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, ObjectHolder from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, typed_kwargs, ContainerTypeInfo, KwargInfo from mesonbuild.mesonlib import ( @@ -1527,3 +1527,17 @@ class InternalTests(unittest.TestCase): self.assertRaises(mesonbuild.mesonlib.MesonBugException): i = mesonbuild.interpreter.Interpreter(build, mock=True) pickle.dumps(i) + + def test_major_versions_differ(self) -> None: + # Return True when going to next major release, when going to dev cycle, + # when going to rc cycle or when going out of rc cycle. + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.60.0')) + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.59.99')) + self.assertTrue(coredata.major_versions_differ('0.59.0', '0.60.0.rc1')) + self.assertTrue(coredata.major_versions_differ('0.59.99', '0.60.0.rc1')) + self.assertTrue(coredata.major_versions_differ('0.60.0.rc1', '0.60.0')) + # Return False when going to next point release or when staying in dev/rc cycle. + self.assertFalse(coredata.major_versions_differ('0.60.0', '0.60.0')) + self.assertFalse(coredata.major_versions_differ('0.60.0', '0.60.1')) + self.assertFalse(coredata.major_versions_differ('0.59.99', '0.59.99')) + self.assertFalse(coredata.major_versions_differ('0.60.0.rc1', '0.60.0.rc2')) diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py new file mode 100644 index 0000000..b26404d --- /dev/null +++ b/unittests/platformagnostictests.py @@ -0,0 +1,34 @@ +# Copyright 2021 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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 os +from unittest import skipIf + +from .baseplatformtests import BasePlatformTests +from .helpers import is_ci +from mesonbuild.mesonlib import is_linux + +@skipIf(is_ci() and not is_linux(), "Run only on fast platforms") +class PlatformAgnosticTests(BasePlatformTests): + ''' + Tests that does not need to run on all platforms during CI + ''' + + def test_relative_find_program(self): + ''' + Tests that find_program() with a relative path does not find the program + in current workdir. + ''' + testdir = os.path.join(self.unit_test_dir, '99 relative find program') + self.init(testdir, workdir=testdir) |