aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig1
-rw-r--r--mesonbuild/backend/ninjabackend.py8
-rw-r--r--mesonbuild/compilers/mixins/clang.py2
-rw-r--r--mesonbuild/coredata.py6
-rw-r--r--mesonbuild/interpreter/dependencyfallbacks.py24
-rw-r--r--mesonbuild/interpreter/interpreter.py6
-rw-r--r--mesonbuild/mtest.py9
-rw-r--r--mesonbuild/programs.py3
-rwxr-xr-xrun_unittests.py3
-rw-r--r--test cases/common/98 subproject subdir/meson.build2
-rw-r--r--test cases/common/98 subproject subdir/subprojects/sub_implicit/meson.build2
-rw-r--r--test cases/common/98 subproject subdir/subprojects/sub_implicit/meson_options.txt1
-rwxr-xr-xtest cases/unit/99 relative find program/foo.py3
-rw-r--r--test cases/unit/99 relative find program/meson.build3
-rw-r--r--test cases/unit/99 relative find program/subdir/meson.build2
-rw-r--r--unittests/allplatformstests.py28
-rw-r--r--unittests/internaltests.py16
-rw-r--r--unittests/platformagnostictests.py34
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)