aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci/travis_install.sh4
-rw-r--r--docs/markdown/Reference-manual.md7
-rw-r--r--docs/markdown/howtox.md10
-rw-r--r--docs/markdown/snippets/d-lang_n_debug.md4
-rw-r--r--docs/markdown/snippets/exe_wrapper_for_cross_built_tests.md9
-rw-r--r--docs/markdown/snippets/rpath_behavior.md7
-rw-r--r--mesonbuild/backend/backends.py58
-rw-r--r--mesonbuild/backend/ninjabackend.py11
-rw-r--r--mesonbuild/backend/vs2010backend.py7
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/cmake/interpreter.py6
-rw-r--r--mesonbuild/compilers/c.py5
-rw-r--r--mesonbuild/compilers/compilers.py13
-rw-r--r--mesonbuild/compilers/cpp.py9
-rw-r--r--mesonbuild/compilers/cuda.py7
-rw-r--r--mesonbuild/compilers/d.py25
-rw-r--r--mesonbuild/compilers/fortran.py2
-rw-r--r--mesonbuild/compilers/mixins/arm.py16
-rw-r--r--mesonbuild/compilers/mixins/clang.py9
-rw-r--r--mesonbuild/compilers/mixins/clike.py3
-rw-r--r--mesonbuild/compilers/mixins/islinker.py4
-rw-r--r--mesonbuild/compilers/objc.py2
-rw-r--r--mesonbuild/compilers/objcpp.py2
-rw-r--r--mesonbuild/dependencies/boost.py25
-rw-r--r--mesonbuild/environment.py26
-rw-r--r--mesonbuild/linkers.py49
-rw-r--r--mesonbuild/minstall.py2
-rw-r--r--mesonbuild/modules/__init__.py11
-rw-r--r--mesonbuild/mtest.py43
-rw-r--r--mesonbuild/scripts/depfixer.py32
-rw-r--r--mesonbuild/scripts/symbolextractor.py24
-rw-r--r--msi/createmsi.py2
-rwxr-xr-xrun_project_tests.py85
-rwxr-xr-xrun_unittests.py328
-rw-r--r--test cases/failing/100 fallback consistency/test.json7
-rw-r--r--test cases/failing/101 no native compiler/test.json7
-rw-r--r--test cases/failing/102 subdir parse error/test.json7
-rw-r--r--test cases/failing/103 invalid option file/test.json7
-rw-r--r--test cases/failing/104 no lang/test.json7
-rw-r--r--test cases/failing/105 no glib-compile-resources/test.json7
-rw-r--r--test cases/failing/34 dependency not-required then required/test.json2
-rw-r--r--test cases/failing/36 pkgconfig dependency impossible conditions/test.json7
-rw-r--r--test cases/failing/67 subproj different versions/test.json7
-rw-r--r--test cases/failing/84 gtest dependency with version/test.json7
-rw-r--r--test cases/failing/98 fallback consistency/test.json7
-rw-r--r--test cases/unit/40 external, internal library rpath/built library/meson.build5
-rw-r--r--test cases/unit/40 external, internal library rpath/external library/meson.build6
-rwxr-xr-xtest cases/unit/72 cross test passed/exewrapper.py24
-rw-r--r--test cases/unit/72 cross test passed/meson.build19
-rw-r--r--test cases/unit/72 cross test passed/meson_options.txt5
-rw-r--r--test cases/unit/72 cross test passed/script.py7
-rw-r--r--test cases/unit/72 cross test passed/src/main.c6
-rw-r--r--test cases/unit/73 summary/meson.build (renamed from test cases/unit/72 summary/meson.build)0
-rw-r--r--test cases/unit/73 summary/subprojects/sub/meson.build (renamed from test cases/unit/72 summary/subprojects/sub/meson.build)0
-rw-r--r--test cases/unit/73 summary/subprojects/sub2/meson.build (renamed from test cases/unit/72 summary/subprojects/sub2/meson.build)0
-rw-r--r--test cases/unit/74 wrap file url/meson.build (renamed from test cases/unit/73 wrap file url/meson.build)0
-rw-r--r--test cases/unit/74 wrap file url/subprojects/foo-patch.tar.xz (renamed from test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xz)bin228 -> 228 bytes
-rw-r--r--test cases/unit/74 wrap file url/subprojects/foo.tar.xz (renamed from test cases/unit/73 wrap file url/subprojects/foo.tar.xz)bin216 -> 216 bytes
-rw-r--r--test cases/unit/75 dep files/foo.c (renamed from test cases/unit/74 dep files/foo.c)0
-rw-r--r--test cases/unit/75 dep files/meson.build (renamed from test cases/unit/74 dep files/meson.build)0
-rw-r--r--test cases/unit/76 pkgconfig prefixes/client/client.c8
-rw-r--r--test cases/unit/76 pkgconfig prefixes/client/meson.build3
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val1/meson.build5
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val1/val1.c3
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val1/val1.h1
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val2/meson.build8
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val2/val2.c4
-rw-r--r--test cases/unit/76 pkgconfig prefixes/val2/val2.h1
-rw-r--r--test cases/unit/76 subdir libdir/meson.build (renamed from test cases/unit/75 subdir libdir/meson.build)0
-rw-r--r--test cases/unit/76 subdir libdir/subprojects/flub/meson.build (renamed from test cases/unit/75 subdir libdir/subprojects/flub/meson.build)0
-rw-r--r--test cases/unit/77 global-rpath/meson.build3
-rw-r--r--test cases/unit/77 global-rpath/rpathified.cpp6
-rw-r--r--test cases/unit/77 global-rpath/yonder/meson.build5
-rw-r--r--test cases/unit/77 global-rpath/yonder/yonder.cpp3
-rw-r--r--test cases/unit/77 global-rpath/yonder/yonder.h1
75 files changed, 805 insertions, 239 deletions
diff --git a/ci/travis_install.sh b/ci/travis_install.sh
index 5d191f1..d9d308a 100755
--- a/ci/travis_install.sh
+++ b/ci/travis_install.sh
@@ -7,9 +7,11 @@ msg() { echo -e "\x1b[1;32mINFO: \x1b[37m$*\x1b[0m"; }
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
msg "Running OSX setup"
brew update
+ # Run one macOS build with pkg-config available (pulled in by qt), and the
+ # other (unity=on) without pkg-config
brew install qt ldc llvm ninja
if [[ "$MESON_ARGS" =~ .*unity=on.* ]]; then
- which pkg-config || brew install pkg-config
+ which pkg-config && rm -f $(which pkg-config)
fi
python3 -m pip install jsonschema
elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 1bd5ff0..9b5d657 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1613,6 +1613,13 @@ object](#build-target-object) returned by
object](#external-program-object) returned by
[`find_program()`](#find_program).
+*Since 0.55.0* When cross compiling, if an exe_wrapper is needed and defined
+the environment variable `MESON_EXE_WRAPPER` will be set to the string value
+of that wrapper (implementation detail: using `mesonlib.join_args`). Test
+scripts may use this to run cross built binaries. If your test needs
+`MESON_EXE_WRAPPER` in cross build situations it is your responsibility to
+return code 77 to tell the harness to report "skip"
+
By default, environment variable
[`MALLOC_PERTURB_`](http://man7.org/linux/man-pages/man3/mallopt.3.html)
is automatically set by `meson test` to a random value between 1..255.
diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md
index abf7519..84546b7 100644
--- a/docs/markdown/howtox.md
+++ b/docs/markdown/howtox.md
@@ -271,6 +271,7 @@ This can be used in cases where you want a default value, but might override it
later.
```meson
+# Not needed on Windows!
my_dep = dependency('', required : false)
if host_machine.system() in ['freebsd', 'netbsd', 'openbsd', 'dragonfly']
my_dep = dependency('some dep', required : false)
@@ -278,8 +279,9 @@ elif host_machine.system() == 'linux'
my_dep = dependency('some other dep', required : false)
endif
-# Last ditch effort!
-if no my_dep.found()
- my_dep = meson.get_compiler('c').find_library('dep')
-endif
+executable(
+ 'myexe',
+ my_sources,
+ deps : [my_dep]
+)
```
diff --git a/docs/markdown/snippets/d-lang_n_debug.md b/docs/markdown/snippets/d-lang_n_debug.md
new file mode 100644
index 0000000..59f09e4
--- /dev/null
+++ b/docs/markdown/snippets/d-lang_n_debug.md
@@ -0,0 +1,4 @@
+## b_ndebug support for D language compilers
+
+D Language compilers will now set -release/--release/-frelease (depending on
+the compiler) when the b_ndebug flag is set.
diff --git a/docs/markdown/snippets/exe_wrapper_for_cross_built_tests.md b/docs/markdown/snippets/exe_wrapper_for_cross_built_tests.md
new file mode 100644
index 0000000..ebdd8a7
--- /dev/null
+++ b/docs/markdown/snippets/exe_wrapper_for_cross_built_tests.md
@@ -0,0 +1,9 @@
+## Test scripts are given the exe wrapper if needed
+
+Meson will now set the `MESON_EXE_WRAPPER` as the properly wrapped and joined
+representation. For Unix-like OSes this means python's shelx.join, on Windows
+an implementation that attempts to properly quote windows argument is used.
+This allow wrapper scripts to run test binaries, instead of just skipping.
+
+for example, if the wrapper is `['emulator', '--script']`, it will be passed
+as `MESON_EXE_WRAPPER="emulator --script"`.
diff --git a/docs/markdown/snippets/rpath_behavior.md b/docs/markdown/snippets/rpath_behavior.md
new file mode 100644
index 0000000..c46f0c2
--- /dev/null
+++ b/docs/markdown/snippets/rpath_behavior.md
@@ -0,0 +1,7 @@
+## rpath removal now more careful
+
+On Linux-like systems, meson adds rpath entries to allow running apps
+in the build tree, and then removes those build-time-only
+rpath entries when installing. Rpath entries may also come
+in via LDFLAGS and via .pc files. Meson used to remove those
+latter rpath entries by accident, but is now more careful.
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 7f7c434..840c9a3 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -90,12 +90,13 @@ class InstallData:
self.mesonintrospect = mesonintrospect
class TargetInstallData:
- def __init__(self, fname, outdir, aliases, strip, install_name_mappings, install_rpath, install_mode, optional=False):
+ def __init__(self, fname, outdir, aliases, strip, install_name_mappings, rpath_dirs_to_remove, install_rpath, install_mode, optional=False):
self.fname = fname
self.outdir = outdir
self.aliases = aliases
self.strip = strip
self.install_name_mappings = install_name_mappings
+ self.rpath_dirs_to_remove = rpath_dirs_to_remove
self.install_rpath = install_rpath
self.install_mode = install_mode
self.optional = optional
@@ -118,7 +119,8 @@ class TestSerialisation:
needs_exe_wrapper: bool, is_parallel: bool, cmd_args: T.List[str],
env: build.EnvironmentVariables, should_fail: bool,
timeout: T.Optional[int], workdir: T.Optional[str],
- extra_paths: T.List[str], protocol: TestProtocol, priority: int):
+ extra_paths: T.List[str], protocol: TestProtocol, priority: int,
+ cmd_is_built: bool):
self.name = name
self.project_name = project
self.suite = suite
@@ -137,6 +139,8 @@ class TestSerialisation:
self.protocol = protocol
self.priority = priority
self.needs_exe_wrapper = needs_exe_wrapper
+ self.cmd_is_built = cmd_is_built
+
def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']:
if backend == 'ninja':
@@ -258,7 +262,7 @@ class Backend:
return self.build_to_src
def get_target_private_dir(self, target):
- return os.path.join(self.get_target_dir(target), target.get_id())
+ return os.path.join(self.get_target_filename(target) + '.p')
def get_target_private_dir_abs(self, target):
return os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target))
@@ -443,6 +447,21 @@ class Backend:
return True
return False
+ def get_external_rpath_dirs(self, target):
+ dirs = set()
+ args = []
+ # FIXME: is there a better way?
+ for lang in ['c', 'cpp']:
+ try:
+ args.extend(self.environment.coredata.get_external_link_args(target.for_machine, lang))
+ except Exception:
+ pass
+ for arg in args:
+ if arg.startswith('-Wl,-rpath='):
+ for dir in arg.replace('-Wl,-rpath=','').split(':'):
+ dirs.add(dir)
+ return dirs
+
def rpaths_for_bundled_shared_libraries(self, target, exclude_system=True):
paths = []
for dep in target.external_deps:
@@ -457,6 +476,9 @@ class Backend:
if exclude_system and self._libdir_is_system(libdir, target.compilers, self.environment):
# No point in adding system paths.
continue
+ # Don't remove rpaths specified in LDFLAGS.
+ if libdir in self.get_external_rpath_dirs(target):
+ continue
# Windows doesn't support rpaths, but we use this function to
# emulate rpaths by setting PATH, so also accept DLLs here
if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so', '.dylib']:
@@ -476,6 +498,7 @@ class Backend:
result = OrderedSet()
result.add('meson-out')
result.update(self.rpaths_for_bundled_shared_libraries(target))
+ target.rpath_dirs_to_remove.update([d.encode('utf8') for d in result])
return tuple(result)
def object_filename_from_source(self, target, source):
@@ -768,6 +791,15 @@ class Backend:
# E.g. an external verifier or simulator program run on a generated executable.
# Can always be run without a wrapper.
test_for_machine = MachineChoice.BUILD
+
+ # we allow passing compiled executables to tests, which may be cross built.
+ # We need to consider these as well when considering whether the target is cross or not.
+ for a in t.cmd_args:
+ if isinstance(a, build.BuildTarget):
+ if a.for_machine is MachineChoice.HOST:
+ test_for_machine = MachineChoice.HOST
+ break
+
is_cross = self.environment.is_cross_build(test_for_machine)
if is_cross and self.environment.need_exe_wrapper():
exe_wrapper = self.environment.get_exe_wrapper()
@@ -781,6 +813,7 @@ class Backend:
extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps)
else:
extra_paths = []
+
cmd_args = []
for a in unholder(t.cmd_args):
if isinstance(a, build.BuildTarget):
@@ -790,6 +823,11 @@ class Backend:
cmd_args.append(a)
elif isinstance(a, str):
cmd_args.append(a)
+ elif isinstance(a, build.Executable):
+ p = self.construct_target_rel_path(a, t.workdir)
+ if p == a.get_filename():
+ p = './' + p
+ cmd_args.append(p)
elif isinstance(a, build.Target):
cmd_args.append(self.construct_target_rel_path(a, t.workdir))
else:
@@ -798,7 +836,8 @@ class Backend:
exe_wrapper, self.environment.need_exe_wrapper(),
t.is_parallel, cmd_args, t.env,
t.should_fail, t.timeout, t.workdir,
- extra_paths, t.protocol, t.priority)
+ extra_paths, t.protocol, t.priority,
+ isinstance(exe, build.Executable))
arr.append(ts)
return arr
@@ -1140,6 +1179,7 @@ class Backend:
mappings = t.get_link_deps_mapping(d.prefix, self.environment)
i = TargetInstallData(self.get_target_filename(t), outdirs[0],
t.get_aliases(), should_strip, mappings,
+ t.rpath_dirs_to_remove,
t.install_rpath, install_mode)
d.targets.append(i)
@@ -1157,14 +1197,14 @@ class Backend:
implib_install_dir = self.environment.get_import_lib_dir()
# Install the import library; may not exist for shared modules
i = TargetInstallData(self.get_target_filename_for_linking(t),
- implib_install_dir, {}, False, {}, '', install_mode,
+ implib_install_dir, {}, False, {}, set(), '', install_mode,
optional=isinstance(t, build.SharedModule))
d.targets.append(i)
if not should_strip and t.get_debug_filename():
debug_file = os.path.join(self.get_target_dir(t), t.get_debug_filename())
i = TargetInstallData(debug_file, outdirs[0],
- {}, False, {}, '',
+ {}, False, {}, set(), '',
install_mode, optional=True)
d.targets.append(i)
# Install secondary outputs. Only used for Vala right now.
@@ -1174,7 +1214,7 @@ class Backend:
if outdir is False:
continue
f = os.path.join(self.get_target_dir(t), output)
- i = TargetInstallData(f, outdir, {}, False, {}, None, install_mode)
+ i = TargetInstallData(f, outdir, {}, False, {}, set(), None, install_mode)
d.targets.append(i)
elif isinstance(t, build.CustomTarget):
# If only one install_dir is specified, assume that all
@@ -1187,7 +1227,7 @@ class Backend:
if num_outdirs == 1 and num_out > 1:
for output in t.get_outputs():
f = os.path.join(self.get_target_dir(t), output)
- i = TargetInstallData(f, outdirs[0], {}, False, {}, None, install_mode,
+ i = TargetInstallData(f, outdirs[0], {}, False, {}, set(), None, install_mode,
optional=not t.build_by_default)
d.targets.append(i)
else:
@@ -1196,7 +1236,7 @@ class Backend:
if outdir is False:
continue
f = os.path.join(self.get_target_dir(t), output)
- i = TargetInstallData(f, outdir, {}, False, {}, None, install_mode,
+ i = TargetInstallData(f, outdir, {}, False, {}, set(), None, install_mode,
optional=not t.build_by_default)
d.targets.append(i)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 9b895c9..7300aaf 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -570,7 +570,7 @@ int dummy;
generated_source_files.append(raw_src)
elif self.environment.is_object(rel_src):
obj_list.append(rel_src)
- elif self.environment.is_library(rel_src):
+ elif self.environment.is_library(rel_src) or modules.is_module_library(rel_src):
pass
else:
# Assume anything not specifically a source file is a header. This is because
@@ -585,7 +585,7 @@ int dummy;
o = self.generate_llvm_ir_compile(target, src)
else:
o = self.generate_single_compile(target, src, True,
- header_deps=header_deps)
+ order_deps=header_deps)
obj_list.append(o)
use_pch = self.environment.coredata.base_options.get('b_pch', False)
@@ -1348,7 +1348,8 @@ int dummy;
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
- rpath_args = rustc.build_rpath_args(self.environment,
+ (rpath_args, target.rpath_dirs_to_remove) = \
+ rustc.build_rpath_args(self.environment,
self.environment.get_build_dir(),
target_slashname_workaround_dir,
self.determine_rpath_dirs(target),
@@ -2580,12 +2581,14 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.get_target_dir(target))
else:
target_slashname_workaround_dir = self.get_target_dir(target)
- commands += linker.build_rpath_args(self.environment,
+ (rpath_args, target.rpath_dirs_to_remove) = \
+ linker.build_rpath_args(self.environment,
self.environment.get_build_dir(),
target_slashname_workaround_dir,
self.determine_rpath_dirs(target),
target.build_rpath,
target.install_rpath)
+ commands += rpath_args
# Add libraries generated by custom targets
custom_target_libraries = self.get_custom_target_provided_libraries(target)
commands += extra_args
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index b5803bf..6965c42 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -98,6 +98,9 @@ class Vs2010Backend(backends.Backend):
self.subdirs = {}
self.handled_target_deps = {}
+ def get_target_private_dir(self, target):
+ return os.path.join(self.get_target_dir(target), target.get_id())
+
def generate_custom_generator_commands(self, target, parent_node):
generator_output_files = []
custom_target_include_dirs = []
@@ -821,12 +824,12 @@ class Vs2010Backend(backends.Backend):
clconf = ET.SubElement(compiles, 'ClCompile')
# CRT type; debug or release
if vscrt_type.value == 'from_buildtype':
- if self.buildtype == 'debug' or self.buildtype == 'debugoptimized':
+ if self.buildtype == 'debug':
ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL'
else:
ET.SubElement(type_config, 'UseDebugLibraries').text = 'false'
- ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded'
+ ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL'
elif vscrt_type.value == 'mdd':
ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL'
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 67b92a5..d7f3b66 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -512,6 +512,8 @@ class BuildTarget(Target):
self.d_features = {}
self.pic = False
self.pie = False
+ # Track build_rpath entries so we can remove them at install time
+ self.rpath_dirs_to_remove = set()
# Sources can be:
# 1. Pre-existing source files in the source tree
# 2. Pre-existing sources generated by configure_file in the build tree
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 1e033c7..35eb17c 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -290,10 +290,12 @@ class ConverterTarget:
m = ConverterTarget.std_regex.match(j)
if m:
std = m.group(2)
- if std not in self._all_lang_stds(i):
+ supported = self._all_lang_stds(i)
+ if std not in supported:
mlog.warning(
'Unknown {0}_std "{1}" -> Ignoring. Try setting the project-'
- 'level {0}_std if build errors occur.'.format(i, std),
+ 'level {0}_std if build errors occur. Known '
+ '{0}_stds are: {2}'.format(i, std, ' '.join(supported)),
once=True
)
continue
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 1bc9e84..aac99b4 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -86,9 +86,10 @@ class ClangCCompiler(ClangCompiler, CCompiler):
_C18_VERSION = '>=8.0.0'
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
+ is_cross, info: 'MachineInfo', exe_wrapper=None,
+ defines: T.Optional[T.List[str]] = None, **kwargs):
CCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'0': [],
'1': default_warn_args,
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 385ef5e..f3c171f 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -186,7 +186,7 @@ rust_buildtype_args = {'plain': [],
d_gdc_buildtype_args = {'plain': [],
'debug': [],
'debugoptimized': ['-finline-functions'],
- 'release': ['-frelease', '-finline-functions'],
+ 'release': ['-finline-functions'],
'minsize': [],
'custom': [],
}
@@ -194,7 +194,7 @@ d_gdc_buildtype_args = {'plain': [],
d_ldc_buildtype_args = {'plain': [],
'debug': [],
'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'],
- 'release': ['-release', '-enable-inlining', '-Hkeep-all-bodies'],
+ 'release': ['-enable-inlining', '-Hkeep-all-bodies'],
'minsize': [],
'custom': [],
}
@@ -202,7 +202,7 @@ d_ldc_buildtype_args = {'plain': [],
d_dmd_buildtype_args = {'plain': [],
'debug': [],
'debugoptimized': ['-inline'],
- 'release': ['-release', '-inline'],
+ 'release': ['-inline'],
'minsize': [],
'custom': [],
}
@@ -320,7 +320,7 @@ def get_base_compile_args(options, compiler):
if (options['b_ndebug'].value == 'true' or
(options['b_ndebug'].value == 'if-release' and
options['buildtype'].value in {'release', 'plain'})):
- args += ['-DNDEBUG']
+ args += compiler.get_disable_assert_args()
except KeyError:
pass
# This does not need a try...except
@@ -1077,7 +1077,7 @@ class Compiler:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
@@ -1204,6 +1204,9 @@ class Compiler:
def get_coverage_link_args(self) -> T.List[str]:
return self.linker.get_coverage_args()
+ def get_disable_assert_args(self) -> T.List[str]:
+ return []
+
def get_largefile_args(compiler):
'''
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index d30017f..478a68c 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -155,10 +155,11 @@ class CPPCompiler(CLikeCompiler, Compiler):
class ClangCPPCompiler(ClangCompiler, CPPCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
+ is_cross, info: 'MachineInfo', exe_wrapper=None,
+ defines : T.Optional[T.List[str]] = None, **kwargs):
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -238,7 +239,9 @@ class EmscriptenCPPCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCPPCompile
class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
- CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)
+ CPPCompiler.__init__(self, exelist=exelist, version=version,
+ for_machine=for_machine, is_cross=is_cross,
+ info=info, exe_wrapper=exe_wrapper, **kwargs)
ArmclangCompiler.__init__(self)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index e839f53..4e89f5d 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -271,9 +271,10 @@ class CudaCompiler(Compiler):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return self._cook_link_args(self.host_compiler.build_rpath_args(
- env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath))
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ (rpath_args, rpath_dirs_to_remove) = self.host_compiler.build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
+ return (self._cook_link_args(rpath_args), rpath_dirs_to_remove)
def linker_to_compiler_args(self, args):
return args
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index a83e221..777fa19 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -220,7 +220,7 @@ class DmdLikeCompilerMixin:
def build_rpath_args(self, env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if self.info.is_windows():
- return []
+ return ([], set())
# GNU ld, solaris ld, and lld acting like GNU ld
if self.linker.id.startswith('ld'):
@@ -228,15 +228,16 @@ class DmdLikeCompilerMixin:
# do directly, each argument -rpath and the value to rpath, need to be
# split into two separate arguments both prefaced with the -L=.
args = []
- for r in super().build_rpath_args(
- env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
+ (rpath_args, rpath_dirs_to_remove) = super().build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
+ for r in rpath_args:
if ',' in r:
a, b = r.split(',', maxsplit=1)
args.append(a)
args.append(self.LINKER_PREFIX + b)
else:
args.append(r)
- return args
+ return (args, rpath_dirs_to_remove)
return super().build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
@@ -645,7 +646,8 @@ class GnuDCompiler(GnuCompiler, DCompiler):
'1': default_warn_args,
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt', 'b_coverage']
+ self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic',
+ 'b_vscrt', 'b_coverage', 'b_pgo', 'b_ndebug']
self._has_color_support = version_compare(self.version, '>=4.9')
# dependencies were implemented before, but broken - support was fixed in GCC 7.1+
@@ -684,6 +686,9 @@ class GnuDCompiler(GnuCompiler, DCompiler):
return args
return args + ['-shared-libphobos']
+ def get_disable_assert_args(self):
+ return ['-frelease']
+
class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
@@ -691,7 +696,7 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
info: 'MachineInfo', arch, **kwargs):
DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
self.id = 'llvm'
- self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt']
+ self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
def get_colorout_args(self, colortype):
if colortype == 'always':
@@ -733,6 +738,9 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
return args
return args + ['-link-defaultlib-shared']
+ def get_disable_assert_args(self) -> T.List[str]:
+ return ['--release']
+
class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
@@ -740,7 +748,7 @@ class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
info: 'MachineInfo', arch, **kwargs):
DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
self.id = 'dmd'
- self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt']
+ self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
def get_colorout_args(self, colortype):
if colortype == 'always':
@@ -803,3 +811,6 @@ class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
if self.info.is_windows():
return args
return args + ['-defaultlib=phobos2', '-debuglib=phobos2']
+
+ def get_disable_assert_args(self) -> T.List[str]:
+ return ['-release']
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index c155b5b..af83c0e56 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -424,7 +424,7 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler):
**kwargs):
FortranCompiler.__init__(self, exelist, version, for_machine,
is_cross, info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, [])
self.id = 'flang'
default_warn_args = ['-Minform=inform']
self.warn_args = {'0': [],
diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py
index aa5d15d..2e2ed94 100644
--- a/mesonbuild/compilers/mixins/arm.py
+++ b/mesonbuild/compilers/mixins/arm.py
@@ -27,10 +27,10 @@ if T.TYPE_CHECKING:
arm_buildtype_args = {
'plain': [],
- 'debug': ['-O0', '--debug'],
- 'debugoptimized': ['-O1', '--debug'],
- 'release': ['-O3', '-Otime'],
- 'minsize': ['-O3', '-Ospace'],
+ 'debug': [],
+ 'debugoptimized': [],
+ 'release': [],
+ 'minsize': [],
'custom': [],
} # type: T.Dict[str, T.List[str]]
@@ -38,9 +38,9 @@ arm_optimization_args = {
'0': ['-O0'],
'g': ['-g'],
'1': ['-O1'],
- '2': ['-O2'],
- '3': ['-O3'],
- 's': [],
+ '2': [], # Compiler defaults to -O2
+ '3': ['-O3', '-Otime'],
+ 's': ['-O3'], # Compiler defaults to -Ospace
} # type: T.Dict[str, T.List[str]]
armclang_buildtype_args = {
@@ -181,7 +181,7 @@ class ArmclangCompiler:
# Override CCompiler.get_dependency_gen_args
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
- return []
+ return ['-MD', '-MT', outtarget, '-MF', outfile]
def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return armclang_optimization_args[optimization_level]
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index 1c0ee45..0ee10ad 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -42,9 +42,10 @@ clang_optimization_args = {
} # type: T.Dict[str, T.List[str]]
class ClangCompiler(GnuLikeCompiler):
- def __init__(self):
+ def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__()
self.id = 'clang'
+ self.defines = defines or {}
self.base_options.append('b_colorout')
# TODO: this really should be part of the linker base_options, but
# linkers don't have base_options.
@@ -56,6 +57,12 @@ class ClangCompiler(GnuLikeCompiler):
def get_colorout_args(self, colortype: str) -> T.List[str]:
return clang_color_args[colortype][:]
+ def has_builtin_define(self, define: str) -> bool:
+ return define in self.defines
+
+ def get_builtin_define(self, define: str) -> T.Optional[str]:
+ return self.defines.get(define)
+
def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return clang_optimization_args[optimization_level]
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index e7b0cd2..01c984d 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -1137,3 +1137,6 @@ class CLikeCompiler:
return self.compiles(self.attribute_check_func(name), env,
extra_args=self.get_has_func_attribute_extra_args(name))
+
+ def get_disable_assert_args(self) -> T.List[str]:
+ return ['-DNDEBUG']
diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py
index 681c816..bf1d339 100644
--- a/mesonbuild/compilers/mixins/islinker.py
+++ b/mesonbuild/compilers/mixins/islinker.py
@@ -107,8 +107,8 @@ class BasicLinkerIsCompilerMixin:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
def get_linker_debug_crt_args(self) -> T.List[str]:
return []
diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py
index 52d258d..d351c88 100644
--- a/mesonbuild/compilers/objc.py
+++ b/mesonbuild/compilers/objc.py
@@ -86,7 +86,7 @@ class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
**kwargs):
ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, [])
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'0': [],
'1': default_warn_args,
diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py
index c8b422b..10555b4 100644
--- a/mesonbuild/compilers/objcpp.py
+++ b/mesonbuild/compilers/objcpp.py
@@ -84,7 +84,7 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
is_cross, info: 'MachineInfo', exe_wrapper=None,
**kwargs):
ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, [])
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
'1': default_warn_args,
diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py
index 2e84820..907c0c2 100644
--- a/mesonbuild/dependencies/boost.py
+++ b/mesonbuild/dependencies/boost.py
@@ -22,7 +22,7 @@ from .. import mlog
from .. import mesonlib
from ..environment import Environment
-from .base import (DependencyException, ExternalDependency)
+from .base import DependencyException, ExternalDependency, PkgConfigDependency
from .misc import threads_factory
# On windows 3 directory layouts are supported:
@@ -189,13 +189,13 @@ class BoostLibraryFile():
def __lt__(self, other: T.Any) -> bool:
if isinstance(other, BoostLibraryFile):
return (
- self.mod_name, self.version_lib, self.arch, self.static,
+ self.mod_name, self.static, self.version_lib, self.arch,
not self.mt, not self.runtime_static,
not self.debug, self.runtime_debug, self.python_debug,
self.stlport, self.deprecated_iostreams,
self.name,
) < (
- other.mod_name, other.version_lib, other.arch, other.static,
+ other.mod_name, other.static, other.version_lib, other.arch,
not other.mt, not other.runtime_static,
not other.debug, other.runtime_debug, other.python_debug,
other.stlport, other.deprecated_iostreams,
@@ -605,6 +605,23 @@ class BoostDependency(ExternalDependency):
roots += paths
return roots # Do not add system paths if BOOST_ROOT is present
+ # Try getting the BOOST_ROOT from a boost.pc if it exists. This primarely
+ # allows BoostDependency to find boost from Conan. See #5438
+ try:
+ boost_pc = PkgConfigDependency('boost', self.env, {'required': False})
+ if boost_pc.found():
+ boost_root = boost_pc.get_pkgconfig_variable('prefix', {'default': None})
+ if boost_root:
+ roots += [Path(boost_root)]
+ except DependencyException:
+ pass
+
+ # Add roots from system paths
+ inc_paths = [Path(x) for x in self.clib_compiler.get_default_include_dirs()]
+ inc_paths = [x.parent for x in inc_paths if x.exists()]
+ inc_paths = [x.resolve() for x in inc_paths]
+ roots += inc_paths
+
# Add system paths
if self.env.machines[self.for_machine].is_windows():
# Where boost built from source actually installs it
@@ -626,8 +643,6 @@ class BoostDependency(ExternalDependency):
roots += [x for x in candidates if x.name.lower().startswith('boost') and x.is_dir()]
else:
tmp = [] # type: T.List[Path]
- # Add unix paths
- tmp += [Path(x).parent for x in self.clib_compiler.get_default_include_dirs()]
# Homebrew
brew_boost = Path('/usr/local/Cellar/boost')
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 8fad628..cb6ae7d 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -726,6 +726,28 @@ class Environment:
minor = defines.get('__LCC_MINOR__', '0')
return dot.join((generation, major, minor))
+ @staticmethod
+ def get_clang_compiler_defines(compiler):
+ """
+ Get the list of Clang pre-processor defines
+ """
+ args = compiler + ['-E', '-dM', '-']
+ p, output, error = Popen_safe(args, write='', stdin=subprocess.PIPE)
+ if p.returncode != 0:
+ raise EnvironmentException('Unable to get clang pre-processor defines:\n' + output + error)
+ defines = {}
+ for line in output.split('\n'):
+ if not line:
+ continue
+ d, *rest = line.split(' ', 2)
+ if d != '#define':
+ continue
+ if len(rest) == 1:
+ defines[rest] = True
+ if len(rest) == 2:
+ defines[rest[0]] = rest[1]
+ return defines
+
def _get_compilers(self, lang, for_machine):
'''
The list of compilers is detected in the exact same way for
@@ -1043,6 +1065,8 @@ class Environment:
if 'clang' in out:
linker = None
+ defines = self.get_clang_compiler_defines(compiler)
+
# Even if the for_machine is darwin, we could be using vanilla
# clang.
if 'Apple' in out:
@@ -1063,7 +1087,7 @@ class Environment:
return cls(
ccache + compiler, version, for_machine, is_cross, info,
- exe_wrap, full_version=full_version, linker=linker)
+ exe_wrap, defines, full_version=full_version, linker=linker)
if 'Intel(R) C++ Intel(R)' in err:
version = search_version(err)
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index db735e7..f02c297 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -56,8 +56,8 @@ class StaticLinker:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
return []
@@ -444,8 +444,8 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
@@ -551,12 +551,12 @@ class GnuLikeDynamicLinkerMixin:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin():
- return []
+ return ([], set())
if not rpath_paths and not install_rpath and not build_rpath:
- return []
+ return ([], set())
args = []
origin_placeholder = '$ORIGIN'
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
@@ -564,9 +564,14 @@ class GnuLikeDynamicLinkerMixin:
# is *very* allergic to duplicate -delete_rpath arguments
# when calling depfixer on installation.
all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths])
+ rpath_dirs_to_remove = set()
+ for p in all_paths:
+ rpath_dirs_to_remove.add(p.encode('utf8'))
# Build_rpath is used as-is (it is usually absolute).
if build_rpath != '':
all_paths.add(build_rpath)
+ for p in build_rpath.split(':'):
+ rpath_dirs_to_remove.add(p.encode('utf8'))
# TODO: should this actually be "for (dragonfly|open)bsd"?
if mesonlib.is_dragonflybsd() or mesonlib.is_openbsd():
@@ -590,7 +595,7 @@ class GnuLikeDynamicLinkerMixin:
# TODO: should this actually be "for solaris/sunos"?
if mesonlib.is_sunos():
- return args
+ return (args, rpath_dirs_to_remove)
# Rpaths to use while linking must be absolute. These are not
# written to the binary. Needed only with GNU ld:
@@ -610,7 +615,7 @@ class GnuLikeDynamicLinkerMixin:
for p in rpath_paths:
args.extend(self._apply_prefix('-rpath-link,' + os.path.join(build_dir, p)))
- return args
+ return (args, rpath_dirs_to_remove)
class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
@@ -676,9 +681,9 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not rpath_paths and not install_rpath and not build_rpath:
- return []
+ return ([], set())
# Ensure that there is enough space for install_name_tool in-place
# editing of large RPATHs
args = self._apply_prefix('-headerpad_max_install_names')
@@ -692,7 +697,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
for rp in all_paths:
args.extend(self._apply_prefix('-rpath,' + rp))
- return args
+ return (args, set())
class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
@@ -763,8 +768,8 @@ class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
class CcrxDynamicLinker(DynamicLinker):
@@ -839,8 +844,8 @@ class Xc16DynamicLinker(DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
class C2000DynamicLinker(DynamicLinker):
@@ -938,10 +943,10 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not env.machines[self.for_machine].is_windows():
- return ['-R' + os.path.join(build_dir, p) for p in rpath_paths]
- return []
+ return (['-R' + os.path.join(build_dir, p) for p in rpath_paths], set())
+ return ([], set())
class PGIStaticLinker(StaticLinker):
@@ -1091,9 +1096,9 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not rpath_paths and not install_rpath and not build_rpath:
- return []
+ return ([], set())
processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir)
all_paths = mesonlib.OrderedSet([os.path.join('$ORIGIN', p) for p in processed_rpaths])
if build_rpath != '':
@@ -1108,7 +1113,7 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
paths = padding
else:
paths = paths + ':' + padding
- return self._apply_prefix('-rpath,{}'.format(paths))
+ return (self._apply_prefix('-rpath,{}'.format(paths)), set())
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
suffix: str, soversion: str, darwin_versions: T.Tuple[str, str],
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 9c64429..0be01fe 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -512,7 +512,7 @@ class Installer:
if file_copied:
self.did_install_something = True
try:
- depfixer.fix_rpath(outname, install_rpath, final_path,
+ depfixer.fix_rpath(outname, t.rpath_dirs_to_remove, install_rpath, final_path,
install_name_mappings, verbose=False)
except SystemExit as e:
if isinstance(e.code, int) and e.code == 0:
diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py
index dc86a1b..47be039 100644
--- a/mesonbuild/modules/__init__.py
+++ b/mesonbuild/modules/__init__.py
@@ -57,6 +57,17 @@ def get_include_args(include_dirs, prefix='-I'):
return dirs_str
+def is_module_library(fname):
+ '''
+ Check if the file is a library-like file generated by a module-specific
+ target, such as GirTarget or TypelibTarget
+ '''
+ if hasattr(fname, 'fname'):
+ fname = fname.fname
+ suffix = fname.split('.')[-1]
+ return suffix in ('gir', 'typelib')
+
+
class ModuleReturnValue:
def __init__(self, return_value, new_objects):
self.return_value = return_value
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 4592c90..4aafe62 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -42,7 +42,7 @@ from . import build
from . import environment
from . import mlog
from .dependencies import ExternalProgram
-from .mesonlib import MesonException, get_wine_shortpath, split_args
+from .mesonlib import MesonException, get_wine_shortpath, split_args, join_args
from .backend.backends import TestProtocol
if T.TYPE_CHECKING:
@@ -311,7 +311,7 @@ class TAPParser:
yield self.Version(version=version)
continue
- if len(line) == 0:
+ if not line:
continue
yield self.Error('unexpected input at line {}'.format((lineno,)))
@@ -609,20 +609,20 @@ class SingleTestRunner:
return ['java', '-jar'] + self.test.fname
elif not self.test.is_cross_built and run_with_mono(self.test.fname[0]):
return ['mono'] + self.test.fname
- else:
- if self.test.is_cross_built and self.test.needs_exe_wrapper:
- if self.test.exe_runner is None:
- # Can not run test on cross compiled executable
- # because there is no execute wrapper.
- return None
- else:
- if not self.test.exe_runner.found():
- msg = 'The exe_wrapper defined in the cross file {!r} was not ' \
- 'found. Please check the command and/or add it to PATH.'
- raise TestException(msg.format(self.test.exe_runner.name))
- return self.test.exe_runner.get_command() + self.test.fname
- else:
- return self.test.fname
+ elif self.test.cmd_is_built and self.test.needs_exe_wrapper:
+ if self.test.exe_runner is None:
+ # Can not run test on cross compiled executable
+ # because there is no execute wrapper.
+ return None
+ elif self.test.cmd_is_built:
+ # If the command is not built (ie, its a python script),
+ # then we don't check for the exe-wrapper
+ if not self.test.exe_runner.found():
+ msg = ('The exe_wrapper defined in the cross file {!r} was not '
+ 'found. Please check the command and/or add it to PATH.')
+ raise TestException(msg.format(self.test.exe_runner.name))
+ return self.test.exe_runner.get_command() + self.test.fname
+ return self.test.fname
def run(self) -> TestRun:
cmd = self._get_cmd()
@@ -638,7 +638,7 @@ class SingleTestRunner:
def _run_cmd(self, cmd: T.List[str]) -> TestRun:
starttime = time.time()
- if len(self.test.extra_paths) > 0:
+ if self.test.extra_paths:
self.env['PATH'] = os.pathsep.join(self.test.extra_paths + ['']) + self.env['PATH']
winecmd = []
for c in cmd:
@@ -867,6 +867,9 @@ class TestHarness:
env = os.environ.copy()
test_env = test.env.get_env(env)
env.update(test_env)
+ if (test.is_cross_built and test.needs_exe_wrapper and
+ test.exe_runner and test.exe_runner.found()):
+ env['MESON_EXE_WRAPPER'] = join_args(test.exe_runner.get_command())
return SingleTestRunner(test, test_env, env, options)
def process_test_result(self, result: TestRun) -> None:
@@ -941,7 +944,7 @@ class TestHarness:
self.junit.write()
def print_collected_logs(self) -> None:
- if len(self.collected_logs) > 0:
+ if self.collected_logs:
if len(self.collected_logs) > 10:
print('\nThe output from 10 first failed tests:\n')
else:
@@ -1023,7 +1026,7 @@ class TestHarness:
print('No tests defined.')
return []
- if len(self.options.include_suites) or len(self.options.exclude_suites):
+ if self.options.include_suites or self.options.exclude_suites:
tests = []
for tst in self.tests:
if self.test_suitable(tst):
@@ -1085,7 +1088,7 @@ class TestHarness:
if len(self.suites) > 1 and test.suite:
rv = TestHarness.split_suite_string(test.suite[0])[0]
s = "+".join(TestHarness.split_suite_string(s)[1] for s in test.suite)
- if len(s):
+ if s:
rv += ":"
return rv + s + " / " + test.name
else:
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index 5ba3a97..a3a3eff 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -290,13 +290,13 @@ class Elf(DataSizes):
self.bf.seek(offset)
self.bf.write(newname)
- def fix_rpath(self, new_rpath):
+ def fix_rpath(self, rpath_dirs_to_remove, new_rpath):
# The path to search for can be either rpath or runpath.
# Fix both of them to be sure.
- self.fix_rpathtype_entry(new_rpath, DT_RPATH)
- self.fix_rpathtype_entry(new_rpath, DT_RUNPATH)
+ self.fix_rpathtype_entry(rpath_dirs_to_remove, new_rpath, DT_RPATH)
+ self.fix_rpathtype_entry(rpath_dirs_to_remove, new_rpath, DT_RUNPATH)
- def fix_rpathtype_entry(self, new_rpath, entrynum):
+ def fix_rpathtype_entry(self, rpath_dirs_to_remove, new_rpath, entrynum):
if isinstance(new_rpath, str):
new_rpath = new_rpath.encode('utf8')
rp_off = self.get_entry_offset(entrynum)
@@ -305,7 +305,23 @@ class Elf(DataSizes):
print('File does not have rpath. It should be a fully static executable.')
return
self.bf.seek(rp_off)
+
old_rpath = self.read_str()
+ new_rpaths = []
+ if new_rpath:
+ new_rpaths.append(new_rpath)
+ if old_rpath:
+ # Filter out build-only rpath entries
+ # added by get_link_dep_subdirs() or
+ # specified by user with build_rpath.
+ for dir in old_rpath.split(b':'):
+ if not (dir in rpath_dirs_to_remove or
+ dir == (b'X' * len(dir))):
+ new_rpaths.append(dir)
+
+ # Prepend user-specified new entries while preserving the ones that came from pkgconfig etc.
+ new_rpath = b':'.join(new_rpaths)
+
if len(old_rpath) < len(new_rpath):
sys.exit("New rpath must not be longer than the old one.")
# The linker does read-only string deduplication. If there is a
@@ -343,13 +359,13 @@ class Elf(DataSizes):
entry.write(self.bf)
return None
-def fix_elf(fname, new_rpath, verbose=True):
+def fix_elf(fname, rpath_dirs_to_remove, new_rpath, verbose=True):
with Elf(fname, verbose) as e:
if new_rpath is None:
e.print_rpath()
e.print_runpath()
else:
- e.fix_rpath(new_rpath)
+ e.fix_rpath(rpath_dirs_to_remove, new_rpath)
def get_darwin_rpaths_to_remove(fname):
out = subprocess.check_output(['otool', '-l', fname],
@@ -430,7 +446,7 @@ def fix_jar(fname):
f.truncate()
subprocess.check_call(['jar', 'ufm', fname, 'META-INF/MANIFEST.MF'])
-def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True):
+def fix_rpath(fname, rpath_dirs_to_remove, new_rpath, final_path, install_name_mappings, verbose=True):
global INSTALL_NAME_TOOL
# Static libraries, import libraries, debug information, headers, etc
# never have rpaths
@@ -441,7 +457,7 @@ def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True)
if fname.endswith('.jar'):
fix_jar(fname)
return
- fix_elf(fname, new_rpath, verbose)
+ fix_elf(fname, rpath_dirs_to_remove, new_rpath, verbose)
return
except SystemExit as e:
if isinstance(e.code, int) and e.code == 0:
diff --git a/mesonbuild/scripts/symbolextractor.py b/mesonbuild/scripts/symbolextractor.py
index d393f93..41cca26 100644
--- a/mesonbuild/scripts/symbolextractor.py
+++ b/mesonbuild/scripts/symbolextractor.py
@@ -113,7 +113,10 @@ def gnu_syms(libfilename: str, outfilename: str):
continue
line_split = line.split()
entry = line_split[0:2]
- if len(line_split) >= 4:
+ # Store the size of symbols pointing to data objects so we relink
+ # when those change, which is needed because of copy relocations
+ # https://github.com/mesonbuild/meson/pull/7132#issuecomment-628353702
+ if line_split[1].upper() in ('B', 'G', 'D') and len(line_split) >= 4:
entry += [line_split[3]]
result += [' '.join(entry)]
write_if_changed('\n'.join(result) + '\n', outfilename)
@@ -139,6 +142,23 @@ def osx_syms(libfilename: str, outfilename: str):
result += [' '.join(x.split()[0:2]) for x in output.split('\n')]
write_if_changed('\n'.join(result) + '\n', outfilename)
+def openbsd_syms(libfilename: str, outfilename: str):
+ # Get the name of the library
+ output = call_tool('readelf', ['-d', libfilename])
+ if not output:
+ dummy_syms(outfilename)
+ return
+ result = [x for x in output.split('\n') if 'SONAME' in x]
+ assert(len(result) <= 1)
+ # Get a list of all symbols exported
+ output = call_tool('nm', ['-D', '-P', '-g', libfilename])
+ if not output:
+ dummy_syms(outfilename)
+ return
+ # U = undefined (cope with the lack of --defined-only option)
+ result += [' '.join(x.split()[0:2]) for x in output.split('\n') if x and not x.endswith('U ')]
+ write_if_changed('\n'.join(result) + '\n', outfilename)
+
def cygwin_syms(impfilename: str, outfilename: str):
# Get the name of the library
output = call_tool('dlltool', ['-I', impfilename])
@@ -234,6 +254,8 @@ def gen_symbols(libfilename: str, impfilename: str, outfilename: str, cross_host
gnu_syms(libfilename, outfilename)
elif mesonlib.is_osx():
osx_syms(libfilename, outfilename)
+ elif mesonlib.is_openbsd():
+ openbsd_syms(libfilename, outfilename)
elif mesonlib.is_windows():
if os.path.isfile(impfilename):
windows_syms(impfilename, outfilename)
diff --git a/msi/createmsi.py b/msi/createmsi.py
index f80d1dc..4d03593 100644
--- a/msi/createmsi.py
+++ b/msi/createmsi.py
@@ -153,6 +153,7 @@ class PackageGenerator:
if os.path.exists(sdir):
shutil.rmtree(sdir)
main_stage, ninja_stage = self.staging_dirs
+ dep_data_dir = 'mesonbuild/dependencies/data'
modules = self.get_all_modules_from_dir('mesonbuild/modules')
modules += self.get_all_modules_from_dir('mesonbuild/scripts')
modules += self.get_more_modules()
@@ -174,6 +175,7 @@ class PackageGenerator:
pyinst_cmd += ['meson.py']
subprocess.check_call(pyinst_cmd)
shutil.move(pyinstaller_tmpdir + '/meson', main_stage)
+ shutil.copytree(dep_data_dir, main_stage + '/mesonbuild/dependencies/data')
if not os.path.exists(os.path.join(main_stage, 'meson.exe')):
sys.exit('Meson exe missing from staging dir.')
os.mkdir(ninja_stage)
diff --git a/run_project_tests.py b/run_project_tests.py
index bcfe05c..22c0205 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -594,18 +594,16 @@ def _run_test(test: TestDef, test_build_dir: str, install_dir: str, extra_args,
return testresult
-def gather_tests(testdir: Path) -> T.List[TestDef]:
+def gather_tests(testdir: Path, stdout_mandatory: bool) -> T.List[TestDef]:
tests = [t.name for t in testdir.iterdir() if t.is_dir()]
tests = [t for t in tests if not t.startswith('.')] # Filter non-tests files (dot files, etc)
test_defs = [TestDef(testdir / t, None, []) for t in tests]
all_tests = [] # type: T.List[TestDef]
for t in test_defs:
+ test_def = {}
test_def_file = t.path / 'test.json'
- if not test_def_file.is_file():
- all_tests += [t]
- continue
-
- test_def = json.loads(test_def_file.read_text())
+ if test_def_file.is_file():
+ test_def = json.loads(test_def_file.read_text())
# Handle additional environment variables
env = {} # type: T.Dict[str, str]
@@ -623,6 +621,8 @@ def gather_tests(testdir: Path) -> T.List[TestDef]:
# Handle expected output
stdout = test_def.get('stdout', [])
+ if stdout_mandatory and not stdout:
+ raise RuntimeError("{} must contain a non-empty stdout key".format(test_def_file))
# Handle the do_not_set_opts list
do_not_set_opts = test_def.get('do_not_set_opts', []) # type: T.List[str]
@@ -897,45 +897,50 @@ def detect_tests_to_run(only: T.List[str], use_tmp: bool) -> T.List[T.Tuple[str,
shutil.which('pgfortran') or
shutil.which('ifort'))
- # Name, subdirectory, skip condition.
+ class TestCategory:
+ def __init__(self, category: str, subdir: str, skip: bool = False, stdout_mandatory: bool = False):
+ self.category = category # category name
+ self.subdir = subdir # subdirectory
+ self.skip = skip # skip condition
+ self.stdout_mandatory = stdout_mandatory # expected stdout is mandatory for tests in this categroy
+
all_tests = [
- ('cmake', 'cmake', not shutil.which('cmake') or (os.environ.get('compiler') == 'msvc2015' and under_ci)),
- ('common', 'common', False),
- ('warning-meson', 'warning', False),
- ('failing-meson', 'failing', False),
- ('failing-build', 'failing build', False),
- ('failing-test', 'failing test', False),
- ('keyval', 'keyval', False),
-
- ('platform-osx', 'osx', not mesonlib.is_osx()),
- ('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()),
- ('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()),
-
- ('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()),
- ('C#', 'csharp', skip_csharp(backend)),
- ('vala', 'vala', backend is not Backend.ninja or not shutil.which(os.environ.get('VALAC', 'valac'))),
- ('rust', 'rust', should_skip_rust(backend)),
- ('d', 'd', backend is not Backend.ninja or not have_d_compiler()),
- ('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler(options.use_tmpdir)),
- ('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler(options.use_tmpdir)),
- ('fortran', 'fortran', skip_fortran or backend != Backend.ninja),
- ('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')),
+ TestCategory('cmake', 'cmake', not shutil.which('cmake') or (os.environ.get('compiler') == 'msvc2015' and under_ci)),
+ TestCategory('common', 'common'),
+ TestCategory('warning-meson', 'warning', stdout_mandatory=True),
+ TestCategory('failing-meson', 'failing', stdout_mandatory=True),
+ TestCategory('failing-build', 'failing build'),
+ TestCategory('failing-test', 'failing test'),
+ TestCategory('keyval', 'keyval'),
+ TestCategory('platform-osx', 'osx', not mesonlib.is_osx()),
+ TestCategory('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()),
+ TestCategory('platform-linux', 'linuxlike', mesonlib.is_osx() or mesonlib.is_windows()),
+ TestCategory('java', 'java', backend is not Backend.ninja or mesonlib.is_osx() or not have_java()),
+ TestCategory('C#', 'csharp', skip_csharp(backend)),
+ TestCategory('vala', 'vala', backend is not Backend.ninja or not shutil.which(os.environ.get('VALAC', 'valac'))),
+ TestCategory('rust', 'rust', should_skip_rust(backend)),
+ TestCategory('d', 'd', backend is not Backend.ninja or not have_d_compiler()),
+ TestCategory('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler(options.use_tmpdir)),
+ TestCategory('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler(options.use_tmpdir)),
+ TestCategory('fortran', 'fortran', skip_fortran or backend != Backend.ninja),
+ TestCategory('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')),
# CUDA tests on Windows: use Ninja backend: python run_project_tests.py --only cuda --backend ninja
- ('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')),
- ('python3', 'python3', backend is not Backend.ninja),
- ('python', 'python', backend is not Backend.ninja),
- ('fpga', 'fpga', shutil.which('yosys') is None),
- ('frameworks', 'frameworks', False),
- ('nasm', 'nasm', False),
- ('wasm', 'wasm', shutil.which('emcc') is None or backend is not Backend.ninja),
+ TestCategory('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')),
+ TestCategory('python3', 'python3', backend is not Backend.ninja),
+ TestCategory('python', 'python', backend is not Backend.ninja),
+ TestCategory('fpga', 'fpga', shutil.which('yosys') is None),
+ TestCategory('frameworks', 'frameworks'),
+ TestCategory('nasm', 'nasm'),
+ TestCategory('wasm', 'wasm', shutil.which('emcc') is None or backend is not Backend.ninja),
]
- names = [t[0] for t in all_tests]
- assert names == ALL_TESTS, 'argparse("--only", choices=ALL_TESTS) need to be updated to match all_tests names'
+ categories = [t.category for t in all_tests]
+ assert categories == ALL_TESTS, 'argparse("--only", choices=ALL_TESTS) need to be updated to match all_tests categories'
+
if only:
- ind = [names.index(o) for o in only]
- all_tests = [all_tests[i] for i in ind]
- gathered_tests = [(name, gather_tests(Path('test cases', subdir)), skip) for name, subdir, skip in all_tests]
+ all_tests = [t for t in all_tests if t.category in only]
+
+ gathered_tests = [(t.category, gather_tests(Path('test cases', t.subdir), t.stdout_mandatory), t.skip) for t in all_tests]
return gathered_tests
def run_tests(all_tests: T.List[T.Tuple[str, T.List[TestDef], bool]],
diff --git a/run_unittests.py b/run_unittests.py
index e088467..651e366 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -40,6 +40,7 @@ from contextlib import contextmanager
from glob import glob
from pathlib import (PurePath, Path)
from distutils.dir_util import copy_tree
+import typing
import mesonbuild.mlog
import mesonbuild.depfile
@@ -56,7 +57,7 @@ from mesonbuild.mesonlib import (
BuildDirLock, LibType, MachineChoice, PerMachine, Version, is_windows,
is_osx, is_cygwin, is_dragonflybsd, is_openbsd, is_haiku, is_sunos,
windows_proof_rmtree, python_command, version_compare, split_args,
- quote_arg, relpath
+ quote_arg, relpath, is_linux
)
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import MesonException, EnvironmentException
@@ -2446,9 +2447,12 @@ class AllPlatformTests(BasePlatformTests):
# Check include order for 'someexe'
incs = [a for a in split_args(execmd) if a.startswith("-I")]
self.assertEqual(len(incs), 9)
- # target private dir
- someexe_id = Target.construct_id_from_path("sub4", "someexe", "@exe")
- self.assertPathEqual(incs[0], "-I" + os.path.join("sub4", someexe_id))
+ # Need to run the build so the private dir is created.
+ self.build()
+ pdirs = glob(os.path.join(self.builddir, 'sub4/someexe*.p'))
+ self.assertEqual(len(pdirs), 1)
+ privdir = pdirs[0][len(self.builddir)+1:]
+ self.assertPathEqual(incs[0], "-I" + privdir)
# target build subdir
self.assertPathEqual(incs[1], "-Isub4")
# target source subdir
@@ -2469,7 +2473,10 @@ class AllPlatformTests(BasePlatformTests):
incs = [a for a in split_args(fxecmd) if a.startswith('-I')]
self.assertEqual(len(incs), 9)
# target private dir
- self.assertPathEqual(incs[0], '-Isomefxe@exe')
+ pdirs = glob(os.path.join(self.builddir, 'somefxe*.p'))
+ self.assertEqual(len(pdirs), 1)
+ privdir = pdirs[0][len(self.builddir)+1:]
+ self.assertPathEqual(incs[0], '-I' + privdir)
# target build dir
self.assertPathEqual(incs[1], '-I.')
# target source dir
@@ -3417,67 +3424,6 @@ int main(int argc, char **argv) {
f.write('public class Foo { public static void main() {} }')
self._run(self.meson_command + ['init', '-b'], workdir=tmpdir)
- # The test uses mocking and thus requires that
- # the current process is the one to run the Meson steps.
- # If we are using an external test executable (most commonly
- # in Debian autopkgtests) then the mocking won't work.
- @unittest.skipIf('MESON_EXE' in os.environ, 'MESON_EXE is defined, can not use mocking.')
- def test_cross_file_system_paths(self):
- if is_windows():
- raise unittest.SkipTest('system crossfile paths not defined for Windows (yet)')
- if is_sunos():
- cc = 'gcc'
- else:
- cc = 'cc'
-
- testdir = os.path.join(self.common_test_dir, '1 trivial')
- cross_content = textwrap.dedent("""\
- [binaries]
- c = '/usr/bin/{}'
- ar = '/usr/bin/ar'
- strip = '/usr/bin/ar'
-
- [properties]
-
- [host_machine]
- system = 'linux'
- cpu_family = 'x86'
- cpu = 'i686'
- endian = 'little'
- """.format(cc))
-
- with tempfile.TemporaryDirectory() as d:
- dir_ = os.path.join(d, 'meson', 'cross')
- os.makedirs(dir_)
- with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f:
- f.write(cross_content)
- name = os.path.basename(f.name)
-
- with mock.patch.dict(os.environ, {'XDG_DATA_HOME': d}):
- self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True)
- self.wipe()
-
- with mock.patch.dict(os.environ, {'XDG_DATA_DIRS': d}):
- os.environ.pop('XDG_DATA_HOME', None)
- self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True)
- self.wipe()
-
- with tempfile.TemporaryDirectory() as d:
- dir_ = os.path.join(d, '.local', 'share', 'meson', 'cross')
- os.makedirs(dir_)
- with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f:
- f.write(cross_content)
- name = os.path.basename(f.name)
-
- # If XDG_DATA_HOME is set in the environment running the
- # tests this test will fail, os mock the environment, pop
- # it, then test
- with mock.patch.dict(os.environ):
- os.environ.pop('XDG_DATA_HOME', None)
- with mock.patch('mesonbuild.coredata.os.path.expanduser', lambda x: x.replace('~', d)):
- self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True)
- self.wipe()
-
def test_compiler_run_command(self):
'''
The test checks that the compiler object can be passed to
@@ -4533,7 +4479,7 @@ recommended as it is not supported on some platforms''')
self._run(self.mconf_command + [self.builddir])
def test_summary(self):
- testdir = os.path.join(self.unit_test_dir, '72 summary')
+ testdir = os.path.join(self.unit_test_dir, '73 summary')
out = self.init(testdir)
expected = textwrap.dedent(r'''
Some Subproject 2.0
@@ -4587,7 +4533,7 @@ recommended as it is not supported on some platforms''')
self.assertPathDoesNotExist(os.path.join(self.builddir, prog))
def test_spurious_reconfigure_built_dep_file(self):
- testdir = os.path.join(self.unit_test_dir, '74 dep files')
+ testdir = os.path.join(self.unit_test_dir, '75 dep files')
# Regression test: Spurious reconfigure was happening when build
# directory is inside source directory.
@@ -5574,6 +5520,10 @@ class LinuxlikeTests(BasePlatformTests):
self.assertRegex('\n'.join(mesonlog),
r'Run-time dependency qt5 \(modules: Core\) found: YES .* \((qmake|qmake-qt5)\)\n')
+ def glob_sofiles_without_privdir(self, g):
+ files = glob(g)
+ return [f for f in files if not f.endswith('.p')]
+
def _test_soname_impl(self, libpath, install):
if is_cygwin() or is_osx():
raise unittest.SkipTest('Test only applicable to ELF and linuxlike sonames')
@@ -5589,28 +5539,28 @@ class LinuxlikeTests(BasePlatformTests):
self.assertPathExists(nover)
self.assertFalse(os.path.islink(nover))
self.assertEqual(get_soname(nover), 'libnover.so')
- self.assertEqual(len(glob(nover[:-3] + '*')), 1)
+ self.assertEqual(len(self.glob_sofiles_without_privdir(nover[:-3] + '*')), 1)
# File with version set
verset = os.path.join(libpath, 'libverset.so')
self.assertPathExists(verset + '.4.5.6')
self.assertEqual(os.readlink(verset), 'libverset.so.4')
self.assertEqual(get_soname(verset), 'libverset.so.4')
- self.assertEqual(len(glob(verset[:-3] + '*')), 3)
+ self.assertEqual(len(self.glob_sofiles_without_privdir(verset[:-3] + '*')), 3)
# File with soversion set
soverset = os.path.join(libpath, 'libsoverset.so')
self.assertPathExists(soverset + '.1.2.3')
self.assertEqual(os.readlink(soverset), 'libsoverset.so.1.2.3')
self.assertEqual(get_soname(soverset), 'libsoverset.so.1.2.3')
- self.assertEqual(len(glob(soverset[:-3] + '*')), 2)
+ self.assertEqual(len(self.glob_sofiles_without_privdir(soverset[:-3] + '*')), 2)
# File with version and soversion set to same values
settosame = os.path.join(libpath, 'libsettosame.so')
self.assertPathExists(settosame + '.7.8.9')
self.assertEqual(os.readlink(settosame), 'libsettosame.so.7.8.9')
self.assertEqual(get_soname(settosame), 'libsettosame.so.7.8.9')
- self.assertEqual(len(glob(settosame[:-3] + '*')), 2)
+ self.assertEqual(len(self.glob_sofiles_without_privdir(settosame[:-3] + '*')), 2)
# File with version and soversion set to different values
bothset = os.path.join(libpath, 'libbothset.so')
@@ -5618,7 +5568,7 @@ class LinuxlikeTests(BasePlatformTests):
self.assertEqual(os.readlink(bothset), 'libbothset.so.1.2.3')
self.assertEqual(os.readlink(bothset + '.1.2.3'), 'libbothset.so.4.5.6')
self.assertEqual(get_soname(bothset), 'libbothset.so.1.2.3')
- self.assertEqual(len(glob(bothset[:-3] + '*')), 3)
+ self.assertEqual(len(self.glob_sofiles_without_privdir(bothset[:-3] + '*')), 3)
def test_soname(self):
self._test_soname_impl(self.builddir, False)
@@ -5738,10 +5688,12 @@ class LinuxlikeTests(BasePlatformTests):
def test_unity_subproj(self):
testdir = os.path.join(self.common_test_dir, '45 subproject')
self.init(testdir, extra_args='--unity=subprojects')
- simpletest_id = Target.construct_id_from_path('subprojects/sublib', 'simpletest', '@exe')
- self.assertPathExists(os.path.join(self.builddir, 'subprojects/sublib', simpletest_id, 'simpletest-unity0.c'))
- sublib_id = Target.construct_id_from_path('subprojects/sublib', 'sublib', '@sha')
- self.assertPathExists(os.path.join(self.builddir, 'subprojects/sublib', sublib_id, 'sublib-unity0.c'))
+ pdirs = glob(os.path.join(self.builddir, 'subprojects/sublib/simpletest*.p'))
+ self.assertEqual(len(pdirs), 1)
+ self.assertPathExists(os.path.join(pdirs[0], 'simpletest-unity0.c'))
+ sdirs = glob(os.path.join(self.builddir, 'subprojects/sublib/*sublib*.p'))
+ self.assertEqual(len(sdirs), 1)
+ self.assertPathExists(os.path.join(sdirs[0], 'sublib-unity0.c'))
self.assertPathDoesNotExist(os.path.join(self.builddir, 'user@exe/user-unity.c'))
self.build()
@@ -6077,6 +6029,39 @@ class LinuxlikeTests(BasePlatformTests):
install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx'))
self.assertEqual(install_rpath, 'baz')
+ def test_global_rpath(self):
+ if is_cygwin():
+ raise unittest.SkipTest('Windows PE/COFF binaries do not use RPATH')
+ if is_osx():
+ raise unittest.SkipTest('Global RPATHs via LDFLAGS not yet supported on MacOS (does anybody need it?)')
+
+ testdir = os.path.join(self.unit_test_dir, '77 global-rpath')
+ oldinstalldir = self.installdir
+
+ # Build and install an external library without DESTDIR.
+ # The external library generates a .pc file without an rpath.
+ yonder_dir = os.path.join(testdir, 'yonder')
+ yonder_prefix = os.path.join(oldinstalldir, 'yonder')
+ yonder_libdir = os.path.join(yonder_prefix, self.libdir)
+ self.prefix = yonder_prefix
+ self.installdir = yonder_prefix
+ self.init(yonder_dir)
+ self.build()
+ self.install(use_destdir=False)
+ self.new_builddir()
+
+ # Build an app that uses that installed library.
+ # Supply the rpath to the installed library via LDFLAGS
+ # (as systems like buildroot and guix are wont to do)
+ # and verify install preserves that rpath.
+ env = {'LDFLAGS': '-Wl,-rpath=' + yonder_libdir,
+ 'PKG_CONFIG_PATH': os.path.join(yonder_libdir, 'pkgconfig')}
+ self.init(testdir, override_envvars=env)
+ self.build()
+ self.install(use_destdir=False)
+ got_rpath = get_rpath(os.path.join(yonder_prefix, 'bin/rpathified'))
+ self.assertEqual(got_rpath, yonder_libdir)
+
@skip_if_not_base_option('b_sanitize')
def test_pch_with_address_sanitizer(self):
if is_cygwin():
@@ -6388,13 +6373,15 @@ class LinuxlikeTests(BasePlatformTests):
self.build(override_envvars=env)
# test uninstalled
self.run_tests(override_envvars=env)
- if not is_osx():
- # Rest of the workflow only works on macOS
+ if not (is_osx() or is_linux()):
return
# test running after installation
self.install(use_destdir=False)
prog = os.path.join(self.installdir, 'bin', 'prog')
self._run([prog])
+ if not is_osx():
+ # Rest of the workflow only works on macOS
+ return
out = self._run(['otool', '-L', prog])
self.assertNotIn('@rpath', out)
## New builddir for testing that DESTDIR is not added to install_name
@@ -6411,6 +6398,57 @@ class LinuxlikeTests(BasePlatformTests):
# Ensure that the otool output does not contain self.installdir
self.assertNotRegex(out, self.installdir + '.*dylib ')
+ @skipIfNoPkgconfig
+ def test_usage_pkgconfig_prefixes(self):
+ '''
+ Build and install two external libraries, to different prefixes,
+ then build and install a client program that finds them via pkgconfig,
+ and verify the installed client program runs.
+ '''
+ oldinstalldir = self.installdir
+
+ # Build and install both external libraries without DESTDIR
+ val1dir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'val1')
+ val1prefix = os.path.join(oldinstalldir, 'val1')
+ self.prefix = val1prefix
+ self.installdir = val1prefix
+ self.init(val1dir)
+ self.build()
+ self.install(use_destdir=False)
+ self.new_builddir()
+
+ env1 = {}
+ env1['PKG_CONFIG_PATH'] = os.path.join(val1prefix, self.libdir, 'pkgconfig')
+ val2dir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'val2')
+ val2prefix = os.path.join(oldinstalldir, 'val2')
+ self.prefix = val2prefix
+ self.installdir = val2prefix
+ self.init(val2dir, override_envvars=env1)
+ self.build()
+ self.install(use_destdir=False)
+ self.new_builddir()
+
+ # Build, install, and run the client program
+ env2 = {}
+ env2['PKG_CONFIG_PATH'] = os.path.join(val2prefix, self.libdir, 'pkgconfig')
+ testdir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'client')
+ testprefix = os.path.join(oldinstalldir, 'client')
+ self.prefix = testprefix
+ self.installdir = testprefix
+ self.init(testdir, override_envvars=env2)
+ self.build()
+ self.install(use_destdir=False)
+ prog = os.path.join(self.installdir, 'bin', 'client')
+ env3 = {}
+ if is_cygwin():
+ env3['PATH'] = os.path.join(val1prefix, 'bin') + \
+ os.pathsep + \
+ os.path.join(val2prefix, 'bin') + \
+ os.pathsep + os.environ['PATH']
+ out = self._run([prog], override_envvars=env3).strip()
+ # Expected output is val1 + val2 = 3
+ self.assertEqual(out, '3')
+
def install_subdir_invalid_symlinks(self, testdir, subdir_path):
'''
Test that installation of broken symlinks works fine.
@@ -6601,7 +6639,7 @@ c = ['{0}']
return hashlib.sha256(f.read()).hexdigest()
def test_wrap_with_file_url(self):
- testdir = os.path.join(self.unit_test_dir, '73 wrap file url')
+ testdir = os.path.join(self.unit_test_dir, '74 wrap file url')
source_filename = os.path.join(testdir, 'subprojects', 'foo.tar.xz')
patch_filename = os.path.join(testdir, 'subprojects', 'foo-patch.tar.xz')
wrap_filename = os.path.join(testdir, 'subprojects', 'foo.wrap')
@@ -6692,7 +6730,7 @@ class LinuxCrossArmTests(BaseLinuxCrossTests):
def test_cross_libdir_subproject(self):
# Guard against a regression where calling "subproject"
# would reset the value of libdir to its default value.
- testdir = os.path.join(self.unit_test_dir, '75 subdir libdir')
+ testdir = os.path.join(self.unit_test_dir, '76 subdir libdir')
self.init(testdir, extra_args=['--libdir=fuf'])
for i in self.introspect('--buildoptions'):
if i['name'] == 'libdir':
@@ -7517,6 +7555,134 @@ class CrossFileTests(BasePlatformTests):
This is mainly aimed to testing overrides from cross files.
"""
+ def _cross_file_generator(self, *, needs_exe_wrapper: bool = False,
+ exe_wrapper: typing.Optional[typing.List[str]] = None) -> str:
+ if is_windows():
+ raise unittest.SkipTest('Cannot run this test on non-mingw/non-cygwin windows')
+ if is_sunos():
+ cc = 'gcc'
+ else:
+ cc = 'cc'
+
+ return textwrap.dedent("""\
+ [binaries]
+ c = '/usr/bin/{}'
+ ar = '/usr/bin/ar'
+ strip = '/usr/bin/ar'
+ {}
+
+ [properties]
+ needs_exe_wrapper = {}
+
+ [host_machine]
+ system = 'linux'
+ cpu_family = 'x86'
+ cpu = 'i686'
+ endian = 'little'
+ """.format(cc,
+ 'exe_wrapper = {}'.format(str(exe_wrapper)) if exe_wrapper is not None else '',
+ needs_exe_wrapper))
+
+ def _stub_exe_wrapper(self) -> str:
+ return textwrap.dedent('''\
+ #!/usr/bin/env python3
+ import subprocess
+ import sys
+
+ sys.exit(subprocess.run(sys.argv[1:]).returncode)
+ ''')
+
+ def test_needs_exe_wrapper_true(self):
+ testdir = os.path.join(self.unit_test_dir, '72 cross test passed')
+ with tempfile.TemporaryDirectory() as d:
+ p = Path(d) / 'crossfile'
+ with p.open('wt') as f:
+ f.write(self._cross_file_generator(needs_exe_wrapper=True))
+ self.init(testdir, extra_args=['--cross-file=' + str(p)])
+ out = self.run_target('test')
+ self.assertRegex(out, r'Skipped:\s*1\s*\n')
+
+ def test_needs_exe_wrapper_false(self):
+ testdir = os.path.join(self.unit_test_dir, '72 cross test passed')
+ with tempfile.TemporaryDirectory() as d:
+ p = Path(d) / 'crossfile'
+ with p.open('wt') as f:
+ f.write(self._cross_file_generator(needs_exe_wrapper=False))
+ self.init(testdir, extra_args=['--cross-file=' + str(p)])
+ out = self.run_target('test')
+ self.assertNotRegex(out, r'Skipped:\s*1\n')
+
+ def test_needs_exe_wrapper_true_wrapper(self):
+ testdir = os.path.join(self.unit_test_dir, '72 cross test passed')
+ with tempfile.TemporaryDirectory() as d:
+ s = Path(d) / 'wrapper.py'
+ with s.open('wt') as f:
+ f.write(self._stub_exe_wrapper())
+ s.chmod(0o774)
+ p = Path(d) / 'crossfile'
+ with p.open('wt') as f:
+ f.write(self._cross_file_generator(
+ needs_exe_wrapper=True,
+ exe_wrapper=[str(s)]))
+
+ self.init(testdir, extra_args=['--cross-file=' + str(p), '-Dexpect=true'])
+ out = self.run_target('test')
+ self.assertRegex(out, r'Ok:\s*3\s*\n')
+
+ def test_cross_exe_passed_no_wrapper(self):
+ testdir = os.path.join(self.unit_test_dir, '72 cross test passed')
+ with tempfile.TemporaryDirectory() as d:
+ p = Path(d) / 'crossfile'
+ with p.open('wt') as f:
+ f.write(self._cross_file_generator(needs_exe_wrapper=True))
+
+ self.init(testdir, extra_args=['--cross-file=' + str(p)])
+ self.build()
+ out = self.run_target('test')
+ self.assertRegex(out, r'Skipped:\s*1\s*\n')
+
+ # The test uses mocking and thus requires that the current process is the
+ # one to run the Meson steps. If we are using an external test executable
+ # (most commonly in Debian autopkgtests) then the mocking won't work.
+ @unittest.skipIf('MESON_EXE' in os.environ, 'MESON_EXE is defined, can not use mocking.')
+ def test_cross_file_system_paths(self):
+ if is_windows():
+ raise unittest.SkipTest('system crossfile paths not defined for Windows (yet)')
+
+ testdir = os.path.join(self.common_test_dir, '1 trivial')
+ cross_content = self._cross_file_generator()
+ with tempfile.TemporaryDirectory() as d:
+ dir_ = os.path.join(d, 'meson', 'cross')
+ os.makedirs(dir_)
+ with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f:
+ f.write(cross_content)
+ name = os.path.basename(f.name)
+
+ with mock.patch.dict(os.environ, {'XDG_DATA_HOME': d}):
+ self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True)
+ self.wipe()
+
+ with mock.patch.dict(os.environ, {'XDG_DATA_DIRS': d}):
+ os.environ.pop('XDG_DATA_HOME', None)
+ self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True)
+ self.wipe()
+
+ with tempfile.TemporaryDirectory() as d:
+ dir_ = os.path.join(d, '.local', 'share', 'meson', 'cross')
+ os.makedirs(dir_)
+ with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f:
+ f.write(cross_content)
+ name = os.path.basename(f.name)
+
+ # If XDG_DATA_HOME is set in the environment running the
+ # tests this test will fail, os mock the environment, pop
+ # it, then test
+ with mock.patch.dict(os.environ):
+ os.environ.pop('XDG_DATA_HOME', None)
+ with mock.patch('mesonbuild.coredata.os.path.expanduser', lambda x: x.replace('~', d)):
+ self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True)
+ self.wipe()
+
def test_cross_file_dirs(self):
testcase = os.path.join(self.unit_test_dir, '60 native file override')
self.init(testcase, default_args=False,
diff --git a/test cases/failing/100 fallback consistency/test.json b/test cases/failing/100 fallback consistency/test.json
new file mode 100644
index 0000000..a783d8c
--- /dev/null
+++ b/test cases/failing/100 fallback consistency/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/100 fallback consistency/meson.build:7:0: ERROR: Inconsistency: Subproject has overridden the dependency with another variable than 'dep2'"
+ }
+ ]
+}
diff --git a/test cases/failing/101 no native compiler/test.json b/test cases/failing/101 no native compiler/test.json
new file mode 100644
index 0000000..c7b5d1c
--- /dev/null
+++ b/test cases/failing/101 no native compiler/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/101 no native compiler/meson.build:12:0: ERROR: No host machine compiler for \"main.c\""
+ }
+ ]
+}
diff --git a/test cases/failing/102 subdir parse error/test.json b/test cases/failing/102 subdir parse error/test.json
new file mode 100644
index 0000000..06fd4d3
--- /dev/null
+++ b/test cases/failing/102 subdir parse error/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/102 subdir parse error/subdir/meson.build:1:0: ERROR: Plusassignment target must be an id."
+ }
+ ]
+}
diff --git a/test cases/failing/103 invalid option file/test.json b/test cases/failing/103 invalid option file/test.json
new file mode 100644
index 0000000..20dbec3
--- /dev/null
+++ b/test cases/failing/103 invalid option file/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/103 invalid option file/meson_options.txt:1:0: ERROR: lexer"
+ }
+ ]
+}
diff --git a/test cases/failing/104 no lang/test.json b/test cases/failing/104 no lang/test.json
new file mode 100644
index 0000000..62999be
--- /dev/null
+++ b/test cases/failing/104 no lang/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/104 no lang/meson.build:2:0: ERROR: No host machine compiler for \"main.c\""
+ }
+ ]
+}
diff --git a/test cases/failing/105 no glib-compile-resources/test.json b/test cases/failing/105 no glib-compile-resources/test.json
new file mode 100644
index 0000000..67dc7e4
--- /dev/null
+++ b/test cases/failing/105 no glib-compile-resources/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/105 no glib-compile-resources/meson.build:8:0: ERROR: Could not execute glib-compile-resources."
+ }
+ ]
+}
diff --git a/test cases/failing/34 dependency not-required then required/test.json b/test cases/failing/34 dependency not-required then required/test.json
index bed1a45..3cf35f5 100644
--- a/test cases/failing/34 dependency not-required then required/test.json
+++ b/test cases/failing/34 dependency not-required then required/test.json
@@ -2,7 +2,7 @@
"stdout": [
{
"match": "re",
- "line": "test cases/failing/34 dependency not\\-required then required/meson\\.build:4:0: ERROR: Dependency \"foo\\-bar\\-xyz\\-12\\.3\" not found, tried .*"
+ "line": ".*/meson\\.build:4:0: ERROR: (Pkg-config binary for machine MachineChoice\\.HOST not found\\. Giving up\\.|Dependency \"foo\\-bar\\-xyz\\-12\\.3\" not found, tried .*)"
}
]
}
diff --git a/test cases/failing/36 pkgconfig dependency impossible conditions/test.json b/test cases/failing/36 pkgconfig dependency impossible conditions/test.json
new file mode 100644
index 0000000..2ce62ac
--- /dev/null
+++ b/test cases/failing/36 pkgconfig dependency impossible conditions/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/36 pkgconfig dependency impossible conditions/meson.build:7:0: ERROR: Dependency 'zlib' was already checked and was not found"
+ }
+ ]
+}
diff --git a/test cases/failing/67 subproj different versions/test.json b/test cases/failing/67 subproj different versions/test.json
new file mode 100644
index 0000000..d16daf9
--- /dev/null
+++ b/test cases/failing/67 subproj different versions/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/67 subproj different versions/subprojects/b/meson.build:3:0: ERROR: Dependency 'c' was already checked and was not found"
+ }
+ ]
+}
diff --git a/test cases/failing/84 gtest dependency with version/test.json b/test cases/failing/84 gtest dependency with version/test.json
new file mode 100644
index 0000000..e1bbcac
--- /dev/null
+++ b/test cases/failing/84 gtest dependency with version/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/84 gtest dependency with version/meson.build:8:0: ERROR: Dependency 'gtest' was already checked and was not found"
+ }
+ ]
+}
diff --git a/test cases/failing/98 fallback consistency/test.json b/test cases/failing/98 fallback consistency/test.json
new file mode 100644
index 0000000..fd77bad
--- /dev/null
+++ b/test cases/failing/98 fallback consistency/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/98 fallback consistency/meson.build:4:0: ERROR: Inconsistency: Subproject has overridden the dependency with another variable than 'dep2'"
+ }
+ ]
+}
diff --git a/test cases/unit/40 external, internal library rpath/built library/meson.build b/test cases/unit/40 external, internal library rpath/built library/meson.build
index f633996..07fe7bb 100644
--- a/test cases/unit/40 external, internal library rpath/built library/meson.build
+++ b/test cases/unit/40 external, internal library rpath/built library/meson.build
@@ -18,4 +18,9 @@ l = shared_library('bar_built', 'bar.c',
if host_machine.system() == 'darwin'
e = executable('prog', 'prog.c', link_with: l, install: true)
test('testprog', e)
+elif host_machine.system() == 'linux'
+ e = executable('prog', 'prog.c', link_with: l, install: true,
+ install_rpath: '$ORIGIN/..' / get_option('libdir'),
+ )
+ test('testprog', e)
endif
diff --git a/test cases/unit/40 external, internal library rpath/external library/meson.build b/test cases/unit/40 external, internal library rpath/external library/meson.build
index 3c311f5..06ffa0f 100644
--- a/test cases/unit/40 external, internal library rpath/external library/meson.build
+++ b/test cases/unit/40 external, internal library rpath/external library/meson.build
@@ -4,16 +4,16 @@ shared_library('foo_in_system', 'foo.c', install : true)
l = shared_library('faa_pkg', 'faa.c', install: true)
if host_machine.system() == 'darwin'
- frameworks = ['-framework', 'CoreFoundation', '-framework', 'CoreMedia']
+ ldflags = ['-framework', 'CoreFoundation', '-framework', 'CoreMedia']
allow_undef_args = ['-Wl,-undefined,dynamic_lookup']
else
- frameworks = []
+ ldflags = ['-Wl,-rpath,${libdir}']
allow_undef_args = []
endif
pkg = import('pkgconfig')
pkg.generate(name: 'faa_pkg',
- libraries: [l] + frameworks,
+ libraries: [l] + ldflags,
description: 'FAA, a pkg-config test library')
# cygwin DLLs can't have undefined symbols
diff --git a/test cases/unit/72 cross test passed/exewrapper.py b/test cases/unit/72 cross test passed/exewrapper.py
new file mode 100755
index 0000000..2c15ed6
--- /dev/null
+++ b/test cases/unit/72 cross test passed/exewrapper.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+# Test that the MESON_EXE_WRAPPER environment variable is set
+
+import argparse
+import os
+import sys
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('binary') # unused, but needed for test behavior
+ parser.add_argument('--expected', action='store_true')
+ args = parser.parse_args()
+
+ defined = 'MESON_EXE_WRAPPER' in os.environ
+
+ if args.expected != defined:
+ print(os.environ, file=sys.stderr)
+ return 1
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/test cases/unit/72 cross test passed/meson.build b/test cases/unit/72 cross test passed/meson.build
new file mode 100644
index 0000000..4deb74b
--- /dev/null
+++ b/test cases/unit/72 cross test passed/meson.build
@@ -0,0 +1,19 @@
+project(
+ 'cross test passed',
+ 'c',
+ version : '>= 0.51'
+)
+
+e = executable('exec', 'src/main.c')
+
+py = import('python').find_installation()
+
+test('root', e)
+test('main', py, args : [meson.current_source_dir() / 'script.py', e])
+
+wrapper_args = []
+if get_option('expect')
+ wrapper_args += '--expected'
+endif
+
+test('exe_wrapper in env', py, args : [meson.current_source_dir() / 'exewrapper.py', e, wrapper_args])
diff --git a/test cases/unit/72 cross test passed/meson_options.txt b/test cases/unit/72 cross test passed/meson_options.txt
new file mode 100644
index 0000000..084c776
--- /dev/null
+++ b/test cases/unit/72 cross test passed/meson_options.txt
@@ -0,0 +1,5 @@
+option(
+ 'expect',
+ type : 'boolean',
+ value : false,
+)
diff --git a/test cases/unit/72 cross test passed/script.py b/test cases/unit/72 cross test passed/script.py
new file mode 100644
index 0000000..257cd30
--- /dev/null
+++ b/test cases/unit/72 cross test passed/script.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python3
+
+import subprocess
+import sys
+
+if __name__ == "__main__":
+ sys.exit(subprocess.run(sys.argv[1:]).returncode)
diff --git a/test cases/unit/72 cross test passed/src/main.c b/test cases/unit/72 cross test passed/src/main.c
new file mode 100644
index 0000000..490b4a6
--- /dev/null
+++ b/test cases/unit/72 cross test passed/src/main.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(int argc, char const *argv[])
+{
+ return 0;
+}
diff --git a/test cases/unit/72 summary/meson.build b/test cases/unit/73 summary/meson.build
index df4540d..df4540d 100644
--- a/test cases/unit/72 summary/meson.build
+++ b/test cases/unit/73 summary/meson.build
diff --git a/test cases/unit/72 summary/subprojects/sub/meson.build b/test cases/unit/73 summary/subprojects/sub/meson.build
index e7d7833..e7d7833 100644
--- a/test cases/unit/72 summary/subprojects/sub/meson.build
+++ b/test cases/unit/73 summary/subprojects/sub/meson.build
diff --git a/test cases/unit/72 summary/subprojects/sub2/meson.build b/test cases/unit/73 summary/subprojects/sub2/meson.build
index 86b9cfd..86b9cfd 100644
--- a/test cases/unit/72 summary/subprojects/sub2/meson.build
+++ b/test cases/unit/73 summary/subprojects/sub2/meson.build
diff --git a/test cases/unit/73 wrap file url/meson.build b/test cases/unit/74 wrap file url/meson.build
index 3bd3b25..3bd3b25 100644
--- a/test cases/unit/73 wrap file url/meson.build
+++ b/test cases/unit/74 wrap file url/meson.build
diff --git a/test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xz b/test cases/unit/74 wrap file url/subprojects/foo-patch.tar.xz
index fdb026c..fdb026c 100644
--- a/test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xz
+++ b/test cases/unit/74 wrap file url/subprojects/foo-patch.tar.xz
Binary files differ
diff --git a/test cases/unit/73 wrap file url/subprojects/foo.tar.xz b/test cases/unit/74 wrap file url/subprojects/foo.tar.xz
index 2ed6ab4..2ed6ab4 100644
--- a/test cases/unit/73 wrap file url/subprojects/foo.tar.xz
+++ b/test cases/unit/74 wrap file url/subprojects/foo.tar.xz
Binary files differ
diff --git a/test cases/unit/74 dep files/foo.c b/test cases/unit/75 dep files/foo.c
index e69de29..e69de29 100644
--- a/test cases/unit/74 dep files/foo.c
+++ b/test cases/unit/75 dep files/foo.c
diff --git a/test cases/unit/74 dep files/meson.build b/test cases/unit/75 dep files/meson.build
index 4829f56..4829f56 100644
--- a/test cases/unit/74 dep files/meson.build
+++ b/test cases/unit/75 dep files/meson.build
diff --git a/test cases/unit/76 pkgconfig prefixes/client/client.c b/test cases/unit/76 pkgconfig prefixes/client/client.c
new file mode 100644
index 0000000..be9bead
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/client/client.c
@@ -0,0 +1,8 @@
+#include <val2.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ printf("%d\n", val2());
+ return 0;
+}
diff --git a/test cases/unit/76 pkgconfig prefixes/client/meson.build b/test cases/unit/76 pkgconfig prefixes/client/meson.build
new file mode 100644
index 0000000..491937b
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/client/meson.build
@@ -0,0 +1,3 @@
+project('client', 'c')
+val2_dep = dependency('val2')
+executable('client', 'client.c', dependencies : [val2_dep], install: true)
diff --git a/test cases/unit/76 pkgconfig prefixes/val1/meson.build b/test cases/unit/76 pkgconfig prefixes/val1/meson.build
new file mode 100644
index 0000000..cc63e31
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val1/meson.build
@@ -0,0 +1,5 @@
+project('val1', 'c')
+val1 = shared_library('val1', 'val1.c', install: true)
+install_headers('val1.h')
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(val1, libraries : ['-Wl,-rpath,${libdir}'])
diff --git a/test cases/unit/76 pkgconfig prefixes/val1/val1.c b/test cases/unit/76 pkgconfig prefixes/val1/val1.c
new file mode 100644
index 0000000..591e521
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val1/val1.c
@@ -0,0 +1,3 @@
+#include "val1.h"
+
+int val1(void) { return 1; }
diff --git a/test cases/unit/76 pkgconfig prefixes/val1/val1.h b/test cases/unit/76 pkgconfig prefixes/val1/val1.h
new file mode 100644
index 0000000..6bd435e
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val1/val1.h
@@ -0,0 +1 @@
+int val1(void);
diff --git a/test cases/unit/76 pkgconfig prefixes/val2/meson.build b/test cases/unit/76 pkgconfig prefixes/val2/meson.build
new file mode 100644
index 0000000..ce69481
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val2/meson.build
@@ -0,0 +1,8 @@
+project('val2', 'c')
+val1_dep = dependency('val1')
+val2 = shared_library('val2', 'val2.c',
+ dependencies : [val1_dep],
+ install: true)
+install_headers('val2.h')
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(val2, libraries : ['-Wl,-rpath,${libdir}'])
diff --git a/test cases/unit/76 pkgconfig prefixes/val2/val2.c b/test cases/unit/76 pkgconfig prefixes/val2/val2.c
new file mode 100644
index 0000000..d7d4857
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val2/val2.c
@@ -0,0 +1,4 @@
+#include "val1.h"
+#include "val2.h"
+
+int val2(void) { return val1() + 2; }
diff --git a/test cases/unit/76 pkgconfig prefixes/val2/val2.h b/test cases/unit/76 pkgconfig prefixes/val2/val2.h
new file mode 100644
index 0000000..995023d
--- /dev/null
+++ b/test cases/unit/76 pkgconfig prefixes/val2/val2.h
@@ -0,0 +1 @@
+int val2(void);
diff --git a/test cases/unit/75 subdir libdir/meson.build b/test cases/unit/76 subdir libdir/meson.build
index 5099c91..5099c91 100644
--- a/test cases/unit/75 subdir libdir/meson.build
+++ b/test cases/unit/76 subdir libdir/meson.build
diff --git a/test cases/unit/75 subdir libdir/subprojects/flub/meson.build b/test cases/unit/76 subdir libdir/subprojects/flub/meson.build
index 7bfd2c5..7bfd2c5 100644
--- a/test cases/unit/75 subdir libdir/subprojects/flub/meson.build
+++ b/test cases/unit/76 subdir libdir/subprojects/flub/meson.build
diff --git a/test cases/unit/77 global-rpath/meson.build b/test cases/unit/77 global-rpath/meson.build
new file mode 100644
index 0000000..c67d9e0
--- /dev/null
+++ b/test cases/unit/77 global-rpath/meson.build
@@ -0,0 +1,3 @@
+project('global-rpath', 'cpp')
+yonder_dep = dependency('yonder')
+executable('rpathified', 'rpathified.cpp', dependencies: [yonder_dep], install: true)
diff --git a/test cases/unit/77 global-rpath/rpathified.cpp b/test cases/unit/77 global-rpath/rpathified.cpp
new file mode 100644
index 0000000..3788906
--- /dev/null
+++ b/test cases/unit/77 global-rpath/rpathified.cpp
@@ -0,0 +1,6 @@
+#include <yonder.h>
+#include <string.h>
+int main(int argc, char **argv)
+{
+ return strcmp(yonder(), "AB54 6BR");
+}
diff --git a/test cases/unit/77 global-rpath/yonder/meson.build b/test cases/unit/77 global-rpath/yonder/meson.build
new file mode 100644
index 0000000..e32f383
--- /dev/null
+++ b/test cases/unit/77 global-rpath/yonder/meson.build
@@ -0,0 +1,5 @@
+project('yonder', 'cpp')
+yonder = shared_library('yonder', 'yonder.cpp', install: true)
+install_headers('yonder.h')
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(yonder)
diff --git a/test cases/unit/77 global-rpath/yonder/yonder.cpp b/test cases/unit/77 global-rpath/yonder/yonder.cpp
new file mode 100644
index 0000000..b182d34
--- /dev/null
+++ b/test cases/unit/77 global-rpath/yonder/yonder.cpp
@@ -0,0 +1,3 @@
+#include "yonder.h"
+
+char *yonder(void) { return "AB54 6BR"; }
diff --git a/test cases/unit/77 global-rpath/yonder/yonder.h b/test cases/unit/77 global-rpath/yonder/yonder.h
new file mode 100644
index 0000000..9d9ad16
--- /dev/null
+++ b/test cases/unit/77 global-rpath/yonder/yonder.h
@@ -0,0 +1 @@
+char *yonder(void);