aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci/travis_install.sh4
-rw-r--r--data/test.schema.json25
-rw-r--r--docs/markdown/Contributing.md27
-rw-r--r--docs/markdown/Cross-compilation.md7
-rw-r--r--docs/markdown/Dependencies.md3
-rw-r--r--docs/markdown/Reference-manual.md12
-rw-r--r--docs/markdown/Reference-tables.md1
-rw-r--r--docs/markdown/howtox.md25
-rw-r--r--docs/markdown/snippets/can_run_host_binaries.md5
-rw-r--r--docs/markdown/snippets/config_tool_no_cross_path.md7
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py4
-rw-r--r--mesonbuild/backend/vs2010backend.py4
-rw-r--r--mesonbuild/build.py9
-rw-r--r--mesonbuild/cmake/interpreter.py19
-rw-r--r--mesonbuild/compilers/compilers.py2
-rw-r--r--mesonbuild/compilers/cpp.py4
-rw-r--r--mesonbuild/compilers/d.py3
-rw-r--r--mesonbuild/compilers/fortran.py12
-rw-r--r--mesonbuild/compilers/mixins/arm.py16
-rw-r--r--mesonbuild/compilers/mixins/clike.py34
-rw-r--r--mesonbuild/coredata.py12
-rw-r--r--mesonbuild/dependencies/base.py25
-rw-r--r--mesonbuild/dependencies/boost.py55
-rw-r--r--mesonbuild/dependencies/ui.py17
-rw-r--r--mesonbuild/envconfig.py1
-rw-r--r--mesonbuild/environment.py20
-rw-r--r--mesonbuild/interpreter.py34
-rw-r--r--mesonbuild/interpreterbase.py60
-rw-r--r--mesonbuild/mesonlib.py10
-rw-r--r--mesonbuild/mlog.py29
-rw-r--r--mesonbuild/modules/__init__.py11
-rw-r--r--mesonbuild/modules/gnome.py10
-rw-r--r--mesonbuild/scripts/symbolextractor.py24
-rw-r--r--msi/createmsi.py2
-rwxr-xr-xrun_project_tests.py68
-rwxr-xr-xrun_tests.py6
-rwxr-xr-xrun_unittests.py21
-rw-r--r--test cases/common/36 tryrun/meson.build2
-rw-r--r--test cases/common/93 selfbuilt custom/meson.build2
-rw-r--r--test cases/failing/1 project not first/test.json7
-rw-r--r--test cases/failing/10 out of bounds/test.json7
-rw-r--r--test cases/failing/11 object arithmetic/test.json8
-rw-r--r--test cases/failing/12 string arithmetic/test.json8
-rw-r--r--test cases/failing/13 array arithmetic/test.json7
-rw-r--r--test cases/failing/14 invalid option name/test.json7
-rw-r--r--test cases/failing/15 kwarg before arg/test.json7
-rw-r--r--test cases/failing/16 extract from subproject/test.json7
-rw-r--r--test cases/failing/17 same target/test.json7
-rw-r--r--test cases/failing/18 wrong plusassign/test.json7
-rw-r--r--test cases/failing/19 target clash/meson.build2
-rw-r--r--test cases/failing/19 target clash/test.json7
-rw-r--r--test cases/failing/2 missing file/test.json7
-rw-r--r--test cases/failing/20 version/test.json8
-rw-r--r--test cases/failing/21 subver/test.json7
-rw-r--r--test cases/failing/22 assert/test.json7
-rw-r--r--test cases/failing/23 rel testdir/test.json7
-rw-r--r--test cases/failing/24 int conversion/test.json7
-rw-r--r--test cases/failing/25 badlang/test.json7
-rw-r--r--test cases/failing/26 output subdir/test.json7
-rw-r--r--test cases/failing/27 noprog use/test.json7
-rw-r--r--test cases/failing/28 no crossprop/test.json7
-rw-r--r--test cases/failing/29 nested ternary/test.json7
-rw-r--r--test cases/failing/3 missing subdir/test.json9
-rw-r--r--test cases/failing/30 invalid man extension/test.json7
-rw-r--r--test cases/failing/31 no man extension/test.json7
-rw-r--r--test cases/failing/32 exe static shared/meson.build2
-rw-r--r--test cases/failing/32 exe static shared/test.json7
-rw-r--r--test cases/failing/33 non-root subproject/test.json7
-rw-r--r--test cases/failing/34 dependency not-required then required/test.json8
-rw-r--r--test cases/failing/35 project argument after target/test.json7
-rw-r--r--test cases/failing/36 pkgconfig dependency impossible conditions/meson.build4
-rw-r--r--test cases/failing/37 has function external dependency/test.json7
-rw-r--r--test cases/failing/38 libdir must be inside prefix/test.json9
-rw-r--r--test cases/failing/39 prefix absolute/test.json10
-rw-r--r--test cases/failing/4 missing meson.build/test.json9
-rw-r--r--test cases/failing/40 kwarg assign/test.json7
-rw-r--r--test cases/failing/41 custom target plainname many inputs/test.json7
-rw-r--r--test cases/failing/42 custom target outputs not matching install_dirs/meson.build2
-rw-r--r--test cases/failing/42 custom target outputs not matching install_dirs/test.json35
-rw-r--r--test cases/failing/43 project name colon/test.json7
-rw-r--r--test cases/failing/44 abs subdir/test.json7
-rw-r--r--test cases/failing/45 abspath to srcdir/test.json7
-rw-r--r--test cases/failing/46 pkgconfig variables reserved/test.json7
-rw-r--r--test cases/failing/47 pkgconfig variables zero length/test.json7
-rw-r--r--test cases/failing/48 pkgconfig variables zero length value/test.json7
-rw-r--r--test cases/failing/49 pkgconfig variables not key value/test.json7
-rw-r--r--test cases/failing/5 misplaced option/test.json7
-rw-r--r--test cases/failing/50 executable comparison/test.json7
-rw-r--r--test cases/failing/51 inconsistent comparison/test.json7
-rw-r--r--test cases/failing/52 slashname/test.json7
-rw-r--r--test cases/failing/53 reserved meson prefix/test.json7
-rw-r--r--test cases/failing/54 wrong shared crate type/meson.build6
-rw-r--r--test cases/failing/54 wrong shared crate type/test.json7
-rw-r--r--test cases/failing/55 wrong static crate type/meson.build6
-rw-r--r--test cases/failing/55 wrong static crate type/test.json7
-rw-r--r--test cases/failing/56 or on new line/test.json7
-rw-r--r--test cases/failing/57 kwarg in module/test.json7
-rw-r--r--test cases/failing/58 link with executable/test.json7
-rw-r--r--test cases/failing/59 assign custom target index/test.json7
-rw-r--r--test cases/failing/6 missing incdir/test.json7
-rw-r--r--test cases/failing/60 getoption prefix/test.json7
-rw-r--r--test cases/failing/61 bad option argument/test.json7
-rw-r--r--test cases/failing/62 subproj filegrab/test.json7
-rw-r--r--test cases/failing/63 grab subproj/test.json7
-rw-r--r--test cases/failing/64 grab sibling/test.json7
-rw-r--r--test cases/failing/65 string as link target/test.json7
-rw-r--r--test cases/failing/66 dependency not-found and required/test.json7
-rw-r--r--test cases/failing/68 wrong boost module/meson.build4
-rw-r--r--test cases/failing/68 wrong boost module/test.json7
-rw-r--r--test cases/failing/69 install_data rename bad size/test.json7
-rw-r--r--test cases/failing/7 go to subproject/test.json7
-rw-r--r--test cases/failing/70 skip only subdir/test.json7
-rw-r--r--test cases/failing/71 dual override/test.json7
-rw-r--r--test cases/failing/72 override used/test.json7
-rw-r--r--test cases/failing/73 run_command unclean exit/test.json8
-rw-r--r--test cases/failing/74 int literal leading zero/test.json8
-rw-r--r--test cases/failing/75 configuration immutable/test.json7
-rw-r--r--test cases/failing/76 link with shared module on osx/meson.build2
-rw-r--r--test cases/failing/76 link with shared module on osx/test.json7
-rw-r--r--test cases/failing/77 non ascii in ascii encoded configure file/test.json8
-rw-r--r--test cases/failing/78 subproj dependency not-found and required/test.json7
-rw-r--r--test cases/failing/79 unfound run/test.json7
-rw-r--r--test cases/failing/8 recursive/test.json7
-rw-r--r--test cases/failing/80 framework dependency with version/meson.build6
-rw-r--r--test cases/failing/80 framework dependency with version/test.json7
-rw-r--r--test cases/failing/81 override exe config/test.json7
-rw-r--r--test cases/failing/82 gl dependency with version/meson.build2
-rw-r--r--test cases/failing/82 gl dependency with version/test.json7
-rw-r--r--test cases/failing/83 threads dependency with version/test.json7
-rw-r--r--test cases/failing/84 gtest dependency with version/meson.build5
-rw-r--r--test cases/failing/85 dub libray/meson.build10
-rw-r--r--test cases/failing/85 dub libray/test.json7
-rw-r--r--test cases/failing/86 dub executable/meson.build10
-rw-r--r--test cases/failing/86 dub executable/test.json7
-rw-r--r--test cases/failing/87 dub compiler/meson.build10
-rw-r--r--test cases/failing/87 dub compiler/test.json14
-rw-r--r--test cases/failing/88 subproj not-found dep/test.json7
-rw-r--r--test cases/failing/89 invalid configure file/test.json7
-rw-r--r--test cases/failing/9 missing extra file/test.json7
-rw-r--r--test cases/failing/90 kwarg dupe/test.json7
-rw-r--r--test cases/failing/91 missing pch file/test.json8
-rw-r--r--test cases/failing/92 pch source different folder/test.json7
-rw-r--r--test cases/failing/93 vala without c/test.json7
-rw-r--r--test cases/failing/94 unknown config tool/test.json7
-rw-r--r--test cases/failing/95 custom target install data/test.json7
-rw-r--r--test cases/failing/96 add dict non string key/test.json7
-rw-r--r--test cases/failing/97 add dict duplicate keys/test.json7
-rw-r--r--test cases/failing/99 no native prop/test.json7
-rw-r--r--test cases/frameworks/21 libwmf/meson.build2
-rw-r--r--test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c124
-rw-r--r--test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h21
-rw-r--r--test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build22
-rw-r--r--test cases/frameworks/7 gnome/gir/dep1/meson.build5
-rw-r--r--test cases/frameworks/7 gnome/gir/meson.build2
-rw-r--r--test cases/frameworks/7 gnome/test.json4
-rw-r--r--test cases/unit/36 exe_wrapper behaviour/meson.build2
-rw-r--r--test cases/warning/1 version for string div/test.json8
-rw-r--r--test cases/warning/2 languages missing native/test.json7
-rwxr-xr-xtools/dircondenser.py4
160 files changed, 1457 insertions, 166 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/data/test.schema.json b/data/test.schema.json
index 72f160f..d3b80d0 100644
--- a/data/test.schema.json
+++ b/data/test.schema.json
@@ -1,5 +1,6 @@
{
"type": "object",
+ "additionalProperties": false,
"properties": {
"env": {
"type": "object",
@@ -100,6 +101,30 @@
"prefix"
]
}
+ },
+ "tools": {
+ "type": "object"
+ },
+ "stdout": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "line": {
+ "type": "string"
+ },
+ "match": {
+ "type": "string",
+ "enum": [
+ "literal",
+ "re"
+ ]
+ }
+ },
+ "required": [
+ "line"
+ ]
+ }
}
}
}
diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md
index 8a24e0b..b16f615 100644
--- a/docs/markdown/Contributing.md
+++ b/docs/markdown/Contributing.md
@@ -329,10 +329,31 @@ Currently supported values are:
#### tools
-This section specifies a list of tool requirements in a simple key-value format.
+This section specifies a dict of tool requirements in a simple key-value format.
If a tool is specified, it has to be present in the environment, and the version
-requirement must be fulfilled match. Otherwise, the entire test is skipped
-(including every element in the test matrix).
+requirement must be fulfilled. Otherwise, the entire test is skipped (including
+every element in the test matrix).
+
+#### stdout
+
+The `stdout` key contains a list of dicts, describing the expected stdout.
+
+Each dict contains the following keys:
+
+- `line`
+- `match` (optional)
+
+Each item in the list is matched, in order, against the remaining actual stdout
+lines, after any previous matches. If the actual stdout is exhausted before
+every item in the list is matched, the expected output has not been seen, and
+the test has failed.
+
+The `match` element of the dict determines how the `line` element is matched:
+
+| Type | Description |
+| -------- | ----------------------- |
+| `literal` | Literal match (default) |
+| `re` | regex match |
### Skipping integration tests
diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md
index 4c4b7bf..1c53dcf 100644
--- a/docs/markdown/Cross-compilation.md
+++ b/docs/markdown/Cross-compilation.md
@@ -231,13 +231,10 @@ The main *meson* object provides two functions to determine cross
compilation status.
```meson
-meson.is_cross_build() # returns true when cross compiling
-meson.has_exe_wrapper() # returns true if an exe wrapper has been defined
+meson.is_cross_build() # returns true when cross compiling
+meson.can_run_host_binaries() # returns true if the host binaries can be run, either with a wrapper or natively
```
-Note that the latter gives undefined return value when doing a native
-build.
-
You can run system checks on both the system compiler or the cross
compiler. You just have to specify which one to use.
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index 17c9991..572a3d1 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -242,6 +242,9 @@ libgcrypt_dep = dependency('libgcrypt', version: '>= 1.8')
gpgme_dep = dependency('gpgme', version: '>= 1.0')
```
+*Since 0.55.0* Meson won't search $PATH any more for a config tool binary when
+cross compiling if the config tool did not have an entry in the cross file.
+
## AppleFrameworks
Use the `modules` keyword to list frameworks required, e.g.
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 97d3e83..1bd5ff0 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1836,10 +1836,14 @@ the following methods.
If `native: false` or not specified, variable is retrieved from the
cross-file if cross-compiling, and from the native-file when not cross-compiling.
-- `has_exe_wrapper()` returns true when doing a cross build if there
- is a wrapper command that can be used to execute cross built
- binaries (for example when cross compiling from Linux to Windows,
- one can use `wine` as the wrapper).
+- `can_run_host_binaries()` returns true if the build machine can run
+ binaries compiled for the host. This returns true unless you are
+ cross compiling, need a helper to run host binaries, and don't have one.
+ For example when cross compiling from Linux to Windows, one can use `wine`
+ as the helper. *New in 0.55.0*
+
+- `has_exe_wrapper()` alias of `can_run_host_binaries`
+ *Deprecated since 0.55.0*
- `install_dependency_manifest(output_name)` installs a manifest file
containing a list of all subprojects, their versions and license
diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md
index dfae339..c42d608 100644
--- a/docs/markdown/Reference-tables.md
+++ b/docs/markdown/Reference-tables.md
@@ -81,6 +81,7 @@ set in the cross file.
| alpha | DEC Alpha processor |
| arc | 32 bit ARC processor |
| arm | 32 bit ARM processor |
+| avr | Atmel AVR processor |
| e2k | MCST Elbrus processor |
| c2000 | 32 bit C2000 processor |
| ia64 | Itanium processor |
diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md
index 8231d3d..84546b7 100644
--- a/docs/markdown/howtox.md
+++ b/docs/markdown/howtox.md
@@ -260,3 +260,28 @@ The `cmake_module_path` property is only needed for custom CMake scripts. System
wide CMake scripts are found automatically.
More information can be found [here](Dependencies.md#cmake)
+
+## Get a default not-found dependency?
+
+```meson
+null_dep = dependency('', required : false)
+```
+
+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)
+elif host_machine.system() == 'linux'
+ my_dep = dependency('some other dep', required : false)
+endif
+
+executable(
+ 'myexe',
+ my_sources,
+ deps : [my_dep]
+)
+```
diff --git a/docs/markdown/snippets/can_run_host_binaries.md b/docs/markdown/snippets/can_run_host_binaries.md
new file mode 100644
index 0000000..0108184
--- /dev/null
+++ b/docs/markdown/snippets/can_run_host_binaries.md
@@ -0,0 +1,5 @@
+## Rename has_exe_wrapper -> can_run_host_binaries
+
+The old name was confusing as it didn't really match the behavior of the
+function. The old name remains as an alias (the behavior hasn't changed), but
+is now deprecated.
diff --git a/docs/markdown/snippets/config_tool_no_cross_path.md b/docs/markdown/snippets/config_tool_no_cross_path.md
new file mode 100644
index 0000000..cec22e4
--- /dev/null
+++ b/docs/markdown/snippets/config_tool_no_cross_path.md
@@ -0,0 +1,7 @@
+## Config tool based dependencies no longer search PATH for cross compiling
+
+Before 0.55.0 config tool based dependencies (llvm-config, cups-config, etc),
+would search system $PATH if they weren't defined in the cross file. This has
+been a source of bugs and has been deprecated. It is now removed, config tool
+binaries must be specified in the cross file now or the dependency will not
+be found.
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 5649909..9d527cb 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -788,7 +788,7 @@ 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
- is_cross = not self.environment.machines.matches_build_machine(test_for_machine)
+ 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()
else:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 49025f9..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)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index b5803bf..614d357 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -821,12 +821,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 7c833a6..360285e 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -497,6 +497,7 @@ class BuildTarget(Target):
self.link_targets = []
self.link_whole_targets = []
self.link_depends = []
+ self.added_deps = set()
self.name_prefix_set = False
self.name_suffix_set = False
self.filename = 'no_name'
@@ -536,6 +537,9 @@ class BuildTarget(Target):
repr_str = "<{0} {1}: {2}>"
return repr_str.format(self.__class__.__name__, self.get_id(), self.filename)
+ def __str__(self):
+ return "{}".format(self.name)
+
def validate_install(self, environment):
if self.for_machine is MachineChoice.BUILD and self.need_install:
if environment.is_cross_build():
@@ -1055,6 +1059,8 @@ This will become a hard error in a future Meson release.''')
def add_deps(self, deps):
deps = listify(deps)
for dep in unholder(deps):
+ if dep in self.added_deps:
+ continue
if isinstance(dep, dependencies.InternalDependency):
# Those parts that are internal.
self.process_sourcelist(dep.sources)
@@ -1093,6 +1099,7 @@ You probably should put it in link_with instead.''')
'either an external dependency (returned by find_library() or '
'dependency()) or an internal dependency (returned by '
'declare_dependency()).'.format(type(dep).__name__))
+ self.added_deps.add(dep)
def get_external_deps(self):
return self.external_deps
@@ -1109,7 +1116,7 @@ You probably should put it in link_with instead.''')
if not isinstance(t, (Target, CustomTargetIndex)):
raise InvalidArguments('{!r} is not a target.'.format(t))
if not t.is_linkable_target():
- raise InvalidArguments('Link target {!r} is not linkable.'.format(t))
+ raise InvalidArguments("Link target '{!s}' is not linkable.".format(t))
if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic:
msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name)
msg += "Use the 'pic' option to static_library to build with PIC."
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 125f18b..35eb17c 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -289,7 +289,17 @@ class ConverterTarget:
for j in self.compile_opts[i]:
m = ConverterTarget.std_regex.match(j)
if m:
- self.override_options += ['{}_std={}'.format(i, m.group(2))]
+ std = m.group(2)
+ 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. Known '
+ '{0}_stds are: {2}'.format(i, std, ' '.join(supported)),
+ once=True
+ )
+ continue
+ self.override_options += ['{}_std={}'.format(i, std)]
elif j in ['-fPIC', '-fpic', '-fPIE', '-fpie']:
self.pie = True
elif j in blacklist_compiler_flags:
@@ -539,6 +549,13 @@ class ConverterTarget:
suffixes += [x for x in exts]
return suffixes
+ @lru_cache(maxsize=None)
+ def _all_lang_stds(self, lang: str) -> T.List[str]:
+ lang_opts = self.env.coredata.compiler_options.build.get(lang, None)
+ if not lang_opts or 'std' not in lang_opts:
+ return []
+ return lang_opts['std'].choices
+
def process_inter_target_dependencies(self):
# Move the dependencies from all transfer_dependencies_from to the target
to_process = list(self.depends)
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index b2bea26..9575273 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -1136,7 +1136,7 @@ class Compiler:
def remove_linkerlike_args(self, args):
rm_exact = ('-headerpad_max_install_names',)
rm_prefixes = ('-Wl,', '-L',)
- rm_next = ('-L',)
+ rm_next = ('-L', '-framework',)
ret = []
iargs = iter(args)
for arg in iargs:
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index d30017f..f4bcfa9 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -238,7 +238,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/d.py b/mesonbuild/compilers/d.py
index e7bd280..d2d03a3 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -646,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']
self._has_color_support = version_compare(self.version, '>=4.9')
# dependencies were implemented before, but broken - support was fixed in GCC 7.1+
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 01283a1..c155b5b 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -214,6 +214,18 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
def language_stdlib_only_link_flags(self) -> T.List[str]:
return ['-lgfortran', '-lm']
+ def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None, disable_cache=False):
+ '''
+ Derived from mixins/clike.py:has_header, but without C-style usage of
+ __has_include which breaks with GCC-Fortran 10:
+ https://github.com/mesonbuild/meson/issues/7017
+ '''
+ fargs = {'prefix': prefix, 'header': hname}
+ code = '{prefix}\n#include <{header}>'
+ return self.compiles(code.format(**fargs), env, extra_args=extra_args,
+ dependencies=dependencies, mode='preprocess', disable_cache=disable_cache)
+
+
class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross, info: 'MachineInfo', exe_wrapper=None,
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/clike.py b/mesonbuild/compilers/mixins/clike.py
index 124c49c..e7b0cd2 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -369,7 +369,8 @@ class CLikeCompiler:
dependencies=dependencies, mode='link', disable_cache=disable_cache)
def run(self, code: str, env, *, extra_args=None, dependencies=None):
- if self.is_cross and self.exe_wrapper is None:
+ need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
+ if need_exe_wrapper and self.exe_wrapper is None:
raise compilers.CrossNoRunException('Can not run test applications in this cross environment.')
with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p:
if p.returncode != 0:
@@ -377,7 +378,7 @@ class CLikeCompiler:
p.input_name,
p.returncode))
return compilers.RunResult(False)
- if self.is_cross:
+ if need_exe_wrapper:
cmdlist = self.exe_wrapper + [p.output_name]
else:
cmdlist = p.output_name
@@ -658,7 +659,7 @@ class CLikeCompiler:
# is not run so we don't care what the return value is.
main = '''\nint main(void) {{
void *a = (void*) &{func};
- long b = (long) a;
+ long long b = (long long) a;
return (int) b;
}}'''
return head, main
@@ -727,24 +728,29 @@ class CLikeCompiler:
# need to look for them differently. On nice compilers like clang, we
# can just directly use the __has_builtin() macro.
fargs['no_includes'] = '#include' not in prefix
- fargs['__builtin_'] = '' if funcname.startswith('__builtin_') else '__builtin_'
+ is_builtin = funcname.startswith('__builtin_')
+ fargs['is_builtin'] = is_builtin
+ fargs['__builtin_'] = '' if is_builtin else '__builtin_'
t = '''{prefix}
int main(void) {{
+
+ /* With some toolchains (MSYS2/mingw for example) the compiler
+ * provides various builtins which are not really implemented and
+ * fall back to the stdlib where they aren't provided and fail at
+ * build/link time. In case the user provides a header, including
+ * the header didn't lead to the function being defined, and the
+ * function we are checking isn't a builtin itself we assume the
+ * builtin is not functional and we just error out. */
+ #if !{no_includes:d} && !defined({func}) && !{is_builtin:d}
+ #error "No definition for {__builtin_}{func} found in the prefix"
+ #endif
+
#ifdef __has_builtin
#if !__has_builtin({__builtin_}{func})
#error "{__builtin_}{func} not found"
#endif
#elif ! defined({func})
- /* Check for {__builtin_}{func} only if no includes were added to the
- * prefix above, which means no definition of {func} can be found.
- * We would always check for this, but we get false positives on
- * MSYS2 if we do. Their toolchain is broken, but we can at least
- * give them a workaround. */
- #if {no_includes:d}
- {__builtin_}{func};
- #else
- #error "No definition for {__builtin_}{func} found in the prefix"
- #endif
+ {__builtin_}{func};
#endif
return 0;
}}'''
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index fcb13f6..8774b80 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -384,8 +384,8 @@ class CoreData:
self.compiler_check_cache = OrderedDict()
# Only to print a warning if it changes between Meson invocations.
self.config_files = self.__load_config_files(options, scratch_dir, 'native')
+ self.builtin_options_libdir_cross_fixup()
self.init_builtins('')
- self.libdir_cross_fixup()
@staticmethod
def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> T.List[str]:
@@ -445,12 +445,12 @@ class CoreData:
raise MesonException('Cannot find specified {} file: {}'.format(ftype, f))
return real
- def libdir_cross_fixup(self):
+ def builtin_options_libdir_cross_fixup(self):
# By default set libdir to "lib" when cross compiling since
# getting the "system default" is always wrong on multiarch
# platforms as it gets a value like lib/x86_64-linux-gnu.
if self.cross_files:
- self.builtins['libdir'].value = 'lib'
+ builtin_options['libdir'].default = 'lib'
def sanitize_prefix(self, prefix):
prefix = os.path.expanduser(prefix)
@@ -491,7 +491,7 @@ class CoreData:
# commonpath will always return a path in the native format, so we
# must use pathlib.PurePath to do the same conversion before
# comparing.
- msg = ('The value of the {!r} option is {!r} which must be a '
+ msg = ('The value of the {!r} option is \'{!s}\' which must be a '
'subdir of the prefix {!r}.\nNote that if you pass a '
'relative path, it is assumed to be a subdir of prefix.')
# os.path.commonpath doesn't understand case-insensitive filesystems,
@@ -682,7 +682,9 @@ class CoreData:
if type(oldval) != type(value):
self.user_options[name] = value
- def is_cross_build(self) -> bool:
+ def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
+ if when_building_for == MachineChoice.BUILD:
+ return False
return len(self.cross_files) > 0
def strip_build_option_names(self, options):
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 95a3956..bcb1531 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -437,28 +437,11 @@ class ConfigToolDependency(ExternalDependency):
"""
if not isinstance(versions, list) and versions is not None:
versions = listify(versions)
-
- tool = self.env.lookup_binary_entry(self.for_machine, self.tool_name)
- if tool is not None:
- tools = [tool]
- else:
- if not self.env.machines.matches_build_machine(self.for_machine):
- mlog.deprecation('No entry for {0} specified in your cross file. '
- 'Falling back to searching PATH. This may find a '
- 'native version of {0}! This will become a hard '
- 'error in a future version of meson'.format(self.tool_name))
- tools = [[t] for t in self.tools]
-
best_match = (None, None)
- for tool in tools:
- if len(tool) == 1:
- # In some situations the command can't be directly executed.
- # For example Shell scripts need to be called through sh on
- # Windows (see issue #1423).
- potential_bin = ExternalProgram(tool[0], silent=True)
- if not potential_bin.found():
- continue
- tool = potential_bin.get_command()
+ for potential_bin in self.search_tool(self.tool_name, self.tool_name, self.tools):
+ if not potential_bin.found():
+ continue
+ tool = potential_bin.get_command()
try:
p, out = Popen_safe(tool + [self.version_arg])[:2]
except (FileNotFoundError, PermissionError):
diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py
index 3262d8b..6e85c53 100644
--- a/mesonbuild/dependencies/boost.py
+++ b/mesonbuild/dependencies/boost.py
@@ -412,10 +412,19 @@ class BoostDependency(ExternalDependency):
break
def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) -> bool:
+ mlog.debug(' - potential library dirs: {}'.format([x.as_posix() for x in lib_dirs]))
+ mlog.debug(' - potential include dirs: {}'.format([x.path.as_posix() for x in inc_dirs]))
+
# 2. Find all boost libraries
libs = [] # type: T.List[BoostLibraryFile]
for i in lib_dirs:
- libs += self.detect_libraries(i)
+ libs = self.detect_libraries(i)
+ if libs:
+ mlog.debug(' - found boost library dir: {}'.format(i))
+ # mlog.debug(' - raw library list:')
+ # for j in libs:
+ # mlog.debug(' - {}'.format(j))
+ break
libs = sorted(set(libs))
modules = ['boost_' + x for x in self.modules]
@@ -423,9 +432,6 @@ class BoostDependency(ExternalDependency):
mlog.debug(' - found boost {} include dir: {}'.format(inc.version, inc.path))
f_libs = self.filter_libraries(libs, inc.version_lib)
- # mlog.debug(' - raw library list:')
- # for j in libs:
- # mlog.debug(' - {}'.format(j))
mlog.debug(' - filtered library list:')
for j in f_libs:
mlog.debug(' - {}'.format(j))
@@ -500,6 +506,19 @@ class BoostDependency(ExternalDependency):
return [self._include_dir_from_version_header(x) for x in candidates]
def detect_lib_dirs(self, root: Path) -> T.List[Path]:
+ # First check the system include paths. Only consider those within the
+ # given root path
+ system_dirs_t = self.clib_compiler.get_library_dirs(self.env)
+ system_dirs = [Path(x) for x in system_dirs_t]
+ system_dirs = [x.resolve() for x in system_dirs if x.exists()]
+ system_dirs = [x for x in system_dirs if mesonlib.path_is_in_root(x, root)]
+ system_dirs = list(mesonlib.OrderedSet(system_dirs))
+
+ if system_dirs:
+ return system_dirs
+
+ # No system include paths were found --> fall back to manually looking
+ # for library dirs in root
dirs = [] # type: T.List[Path]
subdirs = [] # type: T.List[Path]
for i in root.iterdir():
@@ -511,7 +530,25 @@ class BoostDependency(ExternalDependency):
for j in i.iterdir():
if j.is_dir() and j.name.endswith('-linux-gnu'):
subdirs += [j]
- return dirs + subdirs
+
+ # Filter out paths that don't match the target arch to avoid finding
+ # the wrong libraries. See https://github.com/mesonbuild/meson/issues/7110
+ if not self.arch:
+ return dirs + subdirs
+
+ arch_list_32 = ['32', 'i386']
+ arch_list_64 = ['64']
+
+ raw_list = dirs + subdirs
+ no_arch = [x for x in raw_list if not any([y in x.name for y in arch_list_32 + arch_list_64])]
+
+ matching_arch = [] # type: T.List[Path]
+ if '32' in self.arch:
+ matching_arch = [x for x in raw_list if any([y in x.name for y in arch_list_32])]
+ elif '64' in self.arch:
+ matching_arch = [x for x in raw_list if any([y in x.name for y in arch_list_64])]
+
+ return sorted(matching_arch) + sorted(no_arch)
def filter_libraries(self, libs: T.List[BoostLibraryFile], lib_vers: str) -> T.List[BoostLibraryFile]:
# MSVC is very picky with the library tags
@@ -568,6 +605,12 @@ class BoostDependency(ExternalDependency):
roots += paths
return roots # Do not add system paths if BOOST_ROOT is present
+ # 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
@@ -589,8 +632,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/dependencies/ui.py b/mesonbuild/dependencies/ui.py
index 4cec814..741f0b8 100644
--- a/mesonbuild/dependencies/ui.py
+++ b/mesonbuild/dependencies/ui.py
@@ -406,6 +406,9 @@ class QtBaseDependency(ExternalDependency):
if libfile:
libfile = libfile[0]
else:
+ mlog.log("Could not find:", module,
+ self.qtpkgname + module + modules_lib_suffix,
+ 'in', libdir)
self.is_found = False
break
self.link_args.append(libfile)
@@ -426,6 +429,20 @@ class QtBaseDependency(ExternalDependency):
if self.env.machines[self.for_machine].is_darwin():
if is_debug:
suffix += '_debug'
+ if mesonlib.version_compare(self.version, '>= 5.14.0'):
+ if self.env.machines[self.for_machine].is_android():
+ cpu_family = self.env.machines[self.for_machine].cpu_family
+ if cpu_family == 'x86':
+ suffix += '_x86'
+ elif cpu_family == 'x86_64':
+ suffix += '_x86_64'
+ elif cpu_family == 'arm':
+ suffix += '_armeabi-v7a'
+ elif cpu_family == 'aarch64':
+ suffix += '_arm64-v8a'
+ else:
+ mlog.warning('Android target arch {!r} for Qt5 is unknown, '
+ 'module detection may not work'.format(cpu_family))
return suffix
def _link_with_qtmain(self, is_debug, libdir):
diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py
index a4af39a..b74be35 100644
--- a/mesonbuild/envconfig.py
+++ b/mesonbuild/envconfig.py
@@ -40,6 +40,7 @@ known_cpu_families = (
'alpha',
'arc',
'arm',
+ 'avr',
'c2000',
'e2k',
'ia64',
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 4ced8e0..8fad628 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -635,8 +635,8 @@ class Environment:
self.coredata.meson_command = mesonlib.meson_command
self.first_invocation = True
- def is_cross_build(self) -> bool:
- return self.coredata.is_cross_build()
+ def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
+ return self.coredata.is_cross_build(when_building_for)
def dump_coredata(self):
return coredata.save(self.coredata, self.get_build_dir())
@@ -899,7 +899,7 @@ class Environment:
def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice) -> Compiler:
popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine)
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
for compiler in compilers:
@@ -1152,7 +1152,7 @@ class Environment:
def detect_cuda_compiler(self, for_machine):
popen_exceptions = {}
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
compilers, ccache, exe_wrap = self._get_compilers('cuda', for_machine)
info = self.machines[for_machine]
for compiler in compilers:
@@ -1192,7 +1192,7 @@ class Environment:
def detect_fortran_compiler(self, for_machine: MachineChoice):
popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers('fortran', for_machine)
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
for compiler in compilers:
if isinstance(compiler, str):
@@ -1311,7 +1311,7 @@ class Environment:
def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool) -> 'Compiler':
popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers('objc' if objc else 'objcpp', for_machine)
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
for compiler in compilers:
@@ -1402,7 +1402,7 @@ class Environment:
def detect_vala_compiler(self, for_machine):
exelist = self.lookup_binary_entry(for_machine, 'vala')
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
if exelist is None:
# TODO support fallback
@@ -1422,7 +1422,7 @@ class Environment:
def detect_rust_compiler(self, for_machine):
popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine)
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
cc = self.detect_c_compiler(for_machine)
@@ -1513,7 +1513,7 @@ class Environment:
arch = 'x86_mscoff'
popen_exceptions = {}
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
results, ccache, exe_wrap = self._get_compilers('d', for_machine)
for exelist in results:
# Search for a D compiler.
@@ -1604,7 +1604,7 @@ class Environment:
def detect_swift_compiler(self, for_machine):
exelist = self.lookup_binary_entry(for_machine, 'swift')
- is_cross = not self.machines.matches_build_machine(for_machine)
+ is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
if exelist is None:
# TODO support fallback
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index a3e9dee..8c7a82c 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1873,6 +1873,7 @@ class MesonMain(InterpreterObject):
self.methods.update({'get_compiler': self.get_compiler_method,
'is_cross_build': self.is_cross_build_method,
'has_exe_wrapper': self.has_exe_wrapper_method,
+ 'can_run_host_binaries': self.can_run_host_binaries_method,
'is_unity': self.is_unity_method,
'is_subproject': self.is_subproject_method,
'current_source_dir': self.current_source_dir_method,
@@ -2023,9 +2024,16 @@ class MesonMain(InterpreterObject):
@noPosargs
@permittedKwargs({})
- def has_exe_wrapper_method(self, args, kwargs):
- if self.is_cross_build_method(None, None) and \
- self.build.environment.need_exe_wrapper():
+ @FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.')
+ def has_exe_wrapper_method(self, args: T.Tuple[object, ...], kwargs: T.Dict[str, object]) -> bool:
+ return self.can_run_host_binaries_method(args, kwargs)
+
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureNew('meson.can_run_host_binaries', '0.55.0')
+ def can_run_host_binaries_method(self, args: T.Tuple[object, ...], kwargs: T.Dict[str, object]) -> bool:
+ if (self.is_cross_build_method(None, None) and
+ self.build.environment.need_exe_wrapper()):
if self.build.environment.exe_wrapper is None:
return False
# We return True when exe_wrap is defined, when it's not needed, and
@@ -3168,6 +3176,12 @@ external dependencies (including libraries) must go to "dependencies".''')
return should
def add_languages_for(self, args, required, for_machine: MachineChoice):
+ langs = set(self.coredata.compilers[for_machine].keys())
+ langs.update(args)
+ if 'vala' in langs:
+ if 'c' not in langs:
+ raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.')
+
success = True
for lang in sorted(args, key=compilers.sort_clink):
lang = lang.lower()
@@ -3205,11 +3219,6 @@ external dependencies (including libraries) must go to "dependencies".''')
mlog.bold(' '.join(comp.linker.get_exelist())), comp.linker.id, comp.linker.version)
self.build.ensure_static_linker(comp)
- langs = self.coredata.compilers[for_machine].keys()
- if 'vala' in langs:
- if 'c' not in langs:
- raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.')
-
return success
def program_from_file_for(self, for_machine, prognames, silent):
@@ -3950,7 +3959,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
absname = os.path.join(self.environment.get_source_dir(), buildfilename)
if not os.path.isfile(absname):
self.subdir = prev_subdir
- raise InterpreterException('Non-existent build file {!r}'.format(buildfilename))
+ raise InterpreterException("Non-existent build file '{!s}'".format(buildfilename))
with open(absname, encoding='utf8') as f:
code = f.read()
assert(isinstance(code, str))
@@ -3998,7 +4007,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
elif isinstance(s, str):
source_strings.append(s)
else:
- raise InvalidArguments('Argument {!r} must be string or file.'.format(s))
+ raise InvalidArguments('Argument must be string or file.')
sources += self.source_strings_to_files(source_strings)
install_dir = kwargs.get('install_dir', None)
if not isinstance(install_dir, (str, type(None))):
@@ -4272,8 +4281,9 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
for a in incdir_strings:
if a.startswith(src_root):
- raise InvalidArguments('''Tried to form an absolute path to a source dir. You should not do that but use
-relative paths instead.
+ raise InvalidArguments('Tried to form an absolute path to a source dir. '
+ 'You should not do that but use relative paths instead.'
+ '''
To get include path to any directory relative to the current dir do
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 6246a06..af9018b 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -18,6 +18,7 @@
from . import mparser, mesonlib, mlog
from . import environment, dependencies
+import abc
import os, copy, re
import collections.abc
from functools import wraps
@@ -212,17 +213,17 @@ class permittedKwargs:
return f(*wrapped_args, **wrapped_kwargs)
return wrapped
-class FeatureCheckBase:
+class FeatureCheckBase(metaclass=abc.ABCMeta):
"Base class for feature version checks"
- # Class variable, shared across all instances
- #
- # Format: {subproject: {feature_version: set(feature_names)}}
+ # In python 3.6 we can just forward declare this, but in 3.5 we can't
+ # This will be overwritten by the subclasses by necessity
feature_registry = {} # type: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[str]]]]
- def __init__(self, feature_name: str, version: str):
+ def __init__(self, feature_name: str, version: str, extra_message: T.Optional[str] = None):
self.feature_name = feature_name # type: str
self.feature_version = version # type: str
+ self.extra_message = extra_message or '' # type: str
@staticmethod
def get_target_version(subproject: str) -> str:
@@ -231,13 +232,18 @@ class FeatureCheckBase:
return ''
return mesonlib.project_meson_versions[subproject]
+ @staticmethod
+ @abc.abstractmethod
+ def check_version(target_version: str, feature_Version: str) -> bool:
+ pass
+
def use(self, subproject: str) -> None:
tv = self.get_target_version(subproject)
# No target version
if tv == '':
return
# Target version is new enough
- if mesonlib.version_compare_condition_with_min(tv, self.feature_version):
+ if self.check_version(tv, self.feature_version):
return
# Feature is too new for target version, register it
if subproject not in self.feature_registry:
@@ -283,25 +289,57 @@ class FeatureCheckBase:
class FeatureNew(FeatureCheckBase):
"""Checks for new features"""
+ # Class variable, shared across all instances
+ #
+ # Format: {subproject: {feature_version: set(feature_names)}}
+ feature_registry = {} # type: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[str]]]]
+
+ @staticmethod
+ def check_version(target_version: str, feature_version: str) -> bool:
+ return mesonlib.version_compare_condition_with_min(target_version, feature_version)
+
@staticmethod
def get_warning_str_prefix(tv: str) -> str:
return 'Project specifies a minimum meson_version \'{}\' but uses features which were added in newer versions:'.format(tv)
def log_usage_warning(self, tv: str) -> None:
- mlog.warning('Project targeting \'{}\' but tried to use feature introduced '
- 'in \'{}\': {}'.format(tv, self.feature_version, self.feature_name))
+ args = [
+ 'Project targeting', "'{}'".format(tv),
+ 'but tried to use feature introduced in',
+ "'{}':".format(self.feature_version),
+ '{}.'.format(self.feature_name),
+ ]
+ if self.extra_message:
+ args.append(self.extra_message)
+ mlog.warning(*args)
class FeatureDeprecated(FeatureCheckBase):
"""Checks for deprecated features"""
+ # Class variable, shared across all instances
+ #
+ # Format: {subproject: {feature_version: set(feature_names)}}
+ feature_registry = {} # type: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[str]]]]
+
+ @staticmethod
+ def check_version(target_version: str, feature_version: str) -> bool:
+ # For deprecatoin checks we need to return the inverse of FeatureNew checks
+ return not mesonlib.version_compare_condition_with_min(target_version, feature_version)
+
@staticmethod
def get_warning_str_prefix(tv: str) -> str:
return 'Deprecated features used:'
def log_usage_warning(self, tv: str) -> None:
- mlog.deprecation('Project targeting \'{}\' but tried to use feature '
- 'deprecated since \'{}\': {}'
- ''.format(tv, self.feature_version, self.feature_name))
+ args = [
+ 'Project targeting', "'{}'".format(tv),
+ 'but tried to use feature deprecated since',
+ "'{}':".format(self.feature_version),
+ '{}.'.format(self.feature_name),
+ ]
+ if self.extra_message:
+ args.append(self.extra_message)
+ mlog.warning(*args)
class FeatureCheckKwargsBase:
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 6c1e466..b901ec9 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -1533,6 +1533,16 @@ def relpath(path: str, start: str) -> str:
except (TypeError, ValueError):
return path
+def path_is_in_root(path: Path, root: Path, resolve: bool = False) -> bool:
+ # Check wheter a path is within the root directory root
+ try:
+ if resolve:
+ path.resolve().relative_to(root.resolve())
+ else:
+ path.relative_to(root)
+ except ValueError:
+ return False
+ return True
class LibType(Enum):
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index 8cbd248..7b8aec7 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -40,15 +40,32 @@ def _windows_ansi() -> bool:
# original behavior
return bool(kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON'))
-def setup_console() -> bool:
+def colorize_console() -> bool:
+ _colorize_console = getattr(sys.stdout, 'colorize_console', None) # type: bool
+ if _colorize_console is not None:
+ return _colorize_console
+
try:
if platform.system().lower() == 'windows':
- return os.isatty(sys.stdout.fileno()) and _windows_ansi()
- return os.isatty(sys.stdout.fileno()) and os.environ.get('TERM') != 'dumb'
+ _colorize_console = os.isatty(sys.stdout.fileno()) and _windows_ansi()
+ else:
+ _colorize_console = os.isatty(sys.stdout.fileno()) and os.environ.get('TERM', 'dumb') != 'dumb'
except Exception:
- return False
+ _colorize_console = False
+
+ sys.stdout.colorize_console = _colorize_console # type: ignore[attr-defined]
+ return _colorize_console
+
+def setup_console():
+ # on Windows, a subprocess might call SetConsoleMode() on the console
+ # connected to stdout and turn off ANSI escape processing. Call this after
+ # running a subprocess to ensure we turn it on again.
+ if platform.system().lower() == 'windows':
+ try:
+ delattr(sys.stdout, 'colorize_console')
+ except AttributeError:
+ pass
-colorize_console = setup_console()
log_dir = None # type: T.Optional[str]
log_file = None # type: T.Optional[T.TextIO]
log_fname = 'meson-log.txt' # type: str
@@ -204,7 +221,7 @@ def log(*args: T.Union[str, AnsiDecorator], is_error: bool = False,
if log_file is not None:
print(*arr, file=log_file, **kwargs)
log_file.flush()
- if colorize_console:
+ if colorize_console():
arr = process_markup(args, True)
if not log_errors_only or is_error:
force_print(*arr, **kwargs)
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/modules/gnome.py b/mesonbuild/modules/gnome.py
index a97fffa..01acb37 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -695,11 +695,10 @@ class GnomeModule(ExtensionModule):
source.get_subdir())
if subdir not in typelib_includes:
typelib_includes.append(subdir)
- elif isinstance(dep, PkgConfigDependency):
- girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
+ if isinstance(dep, Dependency):
+ girdir = dep.get_variable(pkgconfig='girdir', internal='girdir', default_value='')
if girdir and girdir not in typelib_includes:
typelib_includes.append(girdir)
-
return typelib_includes
def _get_external_args_for_langs(self, state, langs):
@@ -769,7 +768,6 @@ class GnomeModule(ExtensionModule):
external_ldflags += list(self._get_scanner_ldflags(dep_external_ldflags))
girtargets_inc_dirs = self._get_gir_targets_inc_dirs(girtargets)
inc_dirs = self._scan_inc_dirs(kwargs)
- gi_includes.update(gir_inc_dirs + inc_dirs)
scan_command = [giscanner]
scan_command += ['--no-libtool']
@@ -790,7 +788,7 @@ class GnomeModule(ExtensionModule):
scan_command += cflags
scan_command += ['--cflags-end']
scan_command += get_include_args(inc_dirs)
- scan_command += get_include_args(list(gi_includes), prefix='--add-include-path=')
+ scan_command += get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
scan_command += list(internal_ldflags)
scan_command += self._scan_gir_targets(state, girtargets)
scan_command += self._scan_langs(state, [lc[0] for lc in langs_compilers])
@@ -804,7 +802,7 @@ class GnomeModule(ExtensionModule):
typelib_output = '%s-%s.typelib' % (ns, nsversion)
typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@']
- typelib_cmd += get_include_args(list(gi_includes), prefix='--includedir=')
+ typelib_cmd += get_include_args(gir_inc_dirs, prefix='--includedir=')
for incdir in typelib_includes:
typelib_cmd += ["--includedir=" + incdir]
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 9da67b2..bcfe05c 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -191,6 +191,7 @@ class TestDef:
self.env = os.environ.copy()
self.installed_files = [] # type: T.List[InstalledFile]
self.do_not_set_opts = [] # type: T.List[str]
+ self.stdout = [] # type: T.List[T.Dict[str, str]]
def __repr__(self) -> str:
return '<{}: {:<48} [{}: {}] -- {}>'.format(type(self).__name__, str(self.path), self.name, self.args, self.skip)
@@ -341,19 +342,19 @@ def log_text_file(logfile, testdir, stdo, stde):
def bold(text):
- return mlog.bold(text).get_text(mlog.colorize_console)
+ return mlog.bold(text).get_text(mlog.colorize_console())
def green(text):
- return mlog.green(text).get_text(mlog.colorize_console)
+ return mlog.green(text).get_text(mlog.colorize_console())
def red(text):
- return mlog.red(text).get_text(mlog.colorize_console)
+ return mlog.red(text).get_text(mlog.colorize_console())
def yellow(text):
- return mlog.yellow(text).get_text(mlog.colorize_console)
+ return mlog.yellow(text).get_text(mlog.colorize_console())
def _run_ci_include(args: T.List[str]) -> str:
@@ -381,6 +382,55 @@ def run_ci_commands(raw_log: str) -> T.List[str]:
res += ['CI COMMAND {}:\n{}\n'.format(cmd[0], ci_commands[cmd[0]](cmd[1:]))]
return res
+def _compare_output(expected: T.List[T.Dict[str, str]], output: str, desc: str) -> str:
+ if expected:
+ i = iter(expected)
+
+ def next_expected(i):
+ # Get the next expected line
+ item = next(i)
+ how = item.get('match', 'literal')
+ expected = item.get('line')
+
+ # Simple heuristic to automatically convert path separators for
+ # Windows:
+ #
+ # Any '/' appearing before 'WARNING' or 'ERROR' (i.e. a path in a
+ # filename part of a location) is replaced with '\' (in a re: '\\'
+ # which matches a literal '\')
+ #
+ # (There should probably be a way to turn this off for more complex
+ # cases which don't fit this)
+ if mesonlib.is_windows():
+ if how != "re":
+ sub = r'\\'
+ else:
+ sub = r'\\\\'
+ expected = re.sub(r'/(?=.*(WARNING|ERROR))', sub, expected)
+
+ return how, expected
+
+ try:
+ how, expected = next_expected(i)
+ for actual in output.splitlines():
+ if how == "re":
+ match = bool(re.match(expected, actual))
+ else:
+ match = (expected == actual)
+ print(actual)
+ if match:
+ how, expected = next_expected(i)
+
+ # reached the end of output without finding expected
+ return 'expected "{}" not found in {}'.format(expected, desc)
+ except StopIteration:
+ # matched all expected lines
+ pass
+
+ return ''
+
+def validate_output(test: TestDef, stdo: str, stde: str) -> str:
+ return _compare_output(test.stdout, stdo, 'stdout')
def run_test_inprocess(testdir):
old_stdout = sys.stdout
@@ -452,6 +502,11 @@ def _run_test(test: TestDef, test_build_dir: str, install_dir: str, extra_args,
cicmds = run_ci_commands(mesonlog)
testresult = TestResult(cicmds)
testresult.add_step(BuildStep.configure, stdo, stde, mesonlog, time.time() - gen_start)
+ output_msg = validate_output(test, stdo, stde)
+ testresult.mlog += output_msg
+ if output_msg:
+ testresult.fail('Unexpected output while configuring.')
+ return testresult
if should_fail == 'meson':
if returncode == 1:
return testresult
@@ -566,6 +621,9 @@ def gather_tests(testdir: Path) -> T.List[TestDef]:
if 'installed' in test_def:
installed = [InstalledFile(x) for x in test_def['installed']]
+ # Handle expected output
+ stdout = test_def.get('stdout', [])
+
# Handle the do_not_set_opts list
do_not_set_opts = test_def.get('do_not_set_opts', []) # type: T.List[str]
@@ -583,6 +641,7 @@ def gather_tests(testdir: Path) -> T.List[TestDef]:
t.env.update(env)
t.installed_files = installed
t.do_not_set_opts = do_not_set_opts
+ t.stdout = stdout
all_tests += [t]
continue
@@ -653,6 +712,7 @@ def gather_tests(testdir: Path) -> T.List[TestDef]:
test.env.update(env)
test.installed_files = installed
test.do_not_set_opts = do_not_set_opts
+ test.stdout = stdout
all_tests += [test]
return sorted(all_tests)
diff --git a/run_tests.py b/run_tests.py
index 005d9a0..44dcf82 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -303,7 +303,7 @@ def run_configure(commandlist, env=None):
return run_configure_inprocess(commandlist, env=env)
def print_system_info():
- print(mlog.bold('System information.').get_text(mlog.colorize_console))
+ print(mlog.bold('System information.').get_text(mlog.colorize_console()))
print('Architecture:', platform.architecture())
print('Machine:', platform.machine())
print('Platform:', platform.system())
@@ -377,7 +377,7 @@ def main():
print(flush=True)
returncode = 0
else:
- print(mlog.bold('Running unittests.').get_text(mlog.colorize_console))
+ print(mlog.bold('Running unittests.').get_text(mlog.colorize_console()))
print(flush=True)
cmd = mesonlib.python_command + ['run_unittests.py', '-v']
if options.failfast:
@@ -390,7 +390,7 @@ def main():
else:
cross_test_args = mesonlib.python_command + ['run_cross_test.py']
for cf in options.cross:
- print(mlog.bold('Running {} cross tests.'.format(cf)).get_text(mlog.colorize_console))
+ print(mlog.bold('Running {} cross tests.'.format(cf)).get_text(mlog.colorize_console()))
print(flush=True)
cmd = cross_test_args + ['cross/' + cf]
if options.failfast:
diff --git a/run_unittests.py b/run_unittests.py
index 8ad64be..b21f785 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1468,14 +1468,14 @@ class DataTests(unittest.TestCase):
class BasePlatformTests(unittest.TestCase):
+ prefix = '/usr'
+ libdir = 'lib'
def setUp(self):
super().setUp()
self.maxDiff = None
src_root = os.path.dirname(__file__)
src_root = os.path.join(os.getcwd(), src_root)
self.src_root = src_root
- self.prefix = '/usr'
- self.libdir = 'lib'
# Get the backend
# FIXME: Extract this from argv?
self.backend = getattr(Backend, os.environ.get('MESON_UNIT_TEST_BACKEND', 'ninja'))
@@ -1588,8 +1588,9 @@ class BasePlatformTests(unittest.TestCase):
extra_args = [extra_args]
args = [srcdir, self.builddir]
if default_args:
- args += ['--prefix', self.prefix,
- '--libdir', self.libdir]
+ args += ['--prefix', self.prefix]
+ if self.libdir:
+ args += ['--libdir', self.libdir]
if self.meson_native_file:
args += ['--native-file', self.meson_native_file]
if self.meson_cross_file:
@@ -5325,7 +5326,7 @@ class DarwinTests(BasePlatformTests):
def test_removing_unused_linker_args(self):
testdir = os.path.join(self.common_test_dir, '108 has arg')
- env = {'CFLAGS': '-L/tmp -L /var/tmp -headerpad_max_install_names -Wl,-export_dynamic'}
+ env = {'CFLAGS': '-L/tmp -L /var/tmp -headerpad_max_install_names -Wl,-export_dynamic -framework Foundation'}
self.init(testdir, override_envvars=env)
@@ -6720,11 +6721,17 @@ c = ['{0}']
os.unlink(wrap_filename)
+class BaseLinuxCrossTests(BasePlatformTests):
+ # Don't pass --libdir when cross-compiling. We have tests that
+ # check whether meson auto-detects it correctly.
+ libdir = None
+
+
def should_run_cross_arm_tests():
return shutil.which('arm-linux-gnueabihf-gcc') and not platform.machine().lower().startswith('arm')
@unittest.skipUnless(not is_windows() and should_run_cross_arm_tests(), "requires ability to cross compile to ARM")
-class LinuxCrossArmTests(BasePlatformTests):
+class LinuxCrossArmTests(BaseLinuxCrossTests):
'''
Tests that cross-compilation to Linux/ARM works
'''
@@ -6805,7 +6812,7 @@ def should_run_cross_mingw_tests():
return shutil.which('x86_64-w64-mingw32-gcc') and not (is_windows() or is_cygwin())
@unittest.skipUnless(not is_windows() and should_run_cross_mingw_tests(), "requires ability to cross compile with MinGW")
-class LinuxCrossMingwTests(BasePlatformTests):
+class LinuxCrossMingwTests(BaseLinuxCrossTests):
'''
Tests that cross-compilation to Windows/MinGW works
'''
diff --git a/test cases/common/36 tryrun/meson.build b/test cases/common/36 tryrun/meson.build
index 261adf2..5580974 100644
--- a/test cases/common/36 tryrun/meson.build
+++ b/test cases/common/36 tryrun/meson.build
@@ -2,7 +2,7 @@ project('tryrun', 'c', 'cpp')
# Complex to exercise all code paths.
if meson.is_cross_build()
- if meson.has_exe_wrapper()
+ if meson.can_run_host_binaries()
compilers = [meson.get_compiler('c', native : false), meson.get_compiler('cpp', native : false)]
else
compilers = [meson.get_compiler('c', native : true), meson.get_compiler('cpp', native : true)]
diff --git a/test cases/common/93 selfbuilt custom/meson.build b/test cases/common/93 selfbuilt custom/meson.build
index 3cc3906..b536352 100644
--- a/test cases/common/93 selfbuilt custom/meson.build
+++ b/test cases/common/93 selfbuilt custom/meson.build
@@ -26,7 +26,7 @@ ctlib = custom_target('ctlib',
build_by_default : true,
)
-if meson.is_cross_build() and meson.has_exe_wrapper()
+if meson.is_cross_build() and meson.can_run_host_binaries()
checkarg_host = executable('checkarg_host', 'checkarg.cpp')
ctlib_host = custom_target(
diff --git a/test cases/failing/1 project not first/test.json b/test cases/failing/1 project not first/test.json
new file mode 100644
index 0000000..70f3c41
--- /dev/null
+++ b/test cases/failing/1 project not first/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "ERROR: First statement must be a call to project"
+ }
+ ]
+}
diff --git a/test cases/failing/10 out of bounds/test.json b/test cases/failing/10 out of bounds/test.json
new file mode 100644
index 0000000..e27d990
--- /dev/null
+++ b/test cases/failing/10 out of bounds/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/10 out of bounds/meson.build:4:0: ERROR: Index 0 out of bounds of array of size 0."
+ }
+ ]
+}
diff --git a/test cases/failing/11 object arithmetic/test.json b/test cases/failing/11 object arithmetic/test.json
new file mode 100644
index 0000000..5339fac
--- /dev/null
+++ b/test cases/failing/11 object arithmetic/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "match": "re",
+ "line": "test cases/failing/11 object arithmetic/meson\\.build:3:0: ERROR: Invalid use of addition: .*"
+ }
+ ]
+}
diff --git a/test cases/failing/12 string arithmetic/test.json b/test cases/failing/12 string arithmetic/test.json
new file mode 100644
index 0000000..476f9bb
--- /dev/null
+++ b/test cases/failing/12 string arithmetic/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "match": "re",
+ "line": "test cases/failing/12 string arithmetic/meson\\.build:3:0: ERROR: Invalid use of addition: .*"
+ }
+ ]
+}
diff --git a/test cases/failing/13 array arithmetic/test.json b/test cases/failing/13 array arithmetic/test.json
new file mode 100644
index 0000000..55056ce
--- /dev/null
+++ b/test cases/failing/13 array arithmetic/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/13 array arithmetic/meson.build:3:0: ERROR: Multiplication works only with integers."
+ }
+ ]
+}
diff --git a/test cases/failing/14 invalid option name/test.json b/test cases/failing/14 invalid option name/test.json
new file mode 100644
index 0000000..71e685d
--- /dev/null
+++ b/test cases/failing/14 invalid option name/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/14 invalid option name/meson_options.txt:1:0: ERROR: Option names can only contain letters, numbers or dashes."
+ }
+ ]
+}
diff --git a/test cases/failing/15 kwarg before arg/test.json b/test cases/failing/15 kwarg before arg/test.json
new file mode 100644
index 0000000..c7f72c3
--- /dev/null
+++ b/test cases/failing/15 kwarg before arg/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/15 kwarg before arg/meson.build:3:0: ERROR: All keyword arguments must be after positional arguments."
+ }
+ ]
+}
diff --git a/test cases/failing/16 extract from subproject/test.json b/test cases/failing/16 extract from subproject/test.json
new file mode 100644
index 0000000..78d45a5
--- /dev/null
+++ b/test cases/failing/16 extract from subproject/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/16 extract from subproject/meson.build:6:0: ERROR: Tried to extract objects from a subproject target."
+ }
+ ]
+}
diff --git a/test cases/failing/17 same target/test.json b/test cases/failing/17 same target/test.json
new file mode 100644
index 0000000..0005ba4
--- /dev/null
+++ b/test cases/failing/17 same target/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/17 same target/meson.build:4:0: ERROR: Tried to create target \"foo\", but a target of that name already exists."
+ }
+ ]
+}
diff --git a/test cases/failing/18 wrong plusassign/test.json b/test cases/failing/18 wrong plusassign/test.json
new file mode 100644
index 0000000..c698f85
--- /dev/null
+++ b/test cases/failing/18 wrong plusassign/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/18 wrong plusassign/meson.build:3:0: ERROR: Plusassignment target must be an id."
+ }
+ ]
+}
diff --git a/test cases/failing/19 target clash/meson.build b/test cases/failing/19 target clash/meson.build
index ca09fb5..4fd0934 100644
--- a/test cases/failing/19 target clash/meson.build
+++ b/test cases/failing/19 target clash/meson.build
@@ -8,7 +8,7 @@ project('clash', 'c')
# output location is redirected.
if host_machine.system() == 'windows' or host_machine.system() == 'cygwin'
- error('This is expected.')
+ error('MESON_SKIP_TEST test only works on platforms where executables have no suffix.')
endif
executable('clash', 'clash.c')
diff --git a/test cases/failing/19 target clash/test.json b/test cases/failing/19 target clash/test.json
new file mode 100644
index 0000000..d22b894
--- /dev/null
+++ b/test cases/failing/19 target clash/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "ERROR: Multiple producers for Ninja target \"clash\". Please rename your targets."
+ }
+ ]
+}
diff --git a/test cases/failing/2 missing file/test.json b/test cases/failing/2 missing file/test.json
new file mode 100644
index 0000000..b95b8b0
--- /dev/null
+++ b/test cases/failing/2 missing file/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/2 missing file/meson.build:3:0: ERROR: File missing.c does not exist."
+ }
+ ]
+}
diff --git a/test cases/failing/20 version/test.json b/test cases/failing/20 version/test.json
new file mode 100644
index 0000000..f330624
--- /dev/null
+++ b/test cases/failing/20 version/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "match": "re",
+ "line": "test cases/failing/20 version/meson\\.build:1:0: ERROR: Meson version is .* but project requires >100\\.0\\.0"
+ }
+ ]
+}
diff --git a/test cases/failing/21 subver/test.json b/test cases/failing/21 subver/test.json
new file mode 100644
index 0000000..f8cfd3a
--- /dev/null
+++ b/test cases/failing/21 subver/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/21 subver/meson.build:3:0: ERROR: Subproject foo version is 1.0.0 but >1.0.0 required."
+ }
+ ]
+}
diff --git a/test cases/failing/22 assert/test.json b/test cases/failing/22 assert/test.json
new file mode 100644
index 0000000..edae999
--- /dev/null
+++ b/test cases/failing/22 assert/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/22 assert/meson.build:3:0: ERROR: Assert failed: I am fail."
+ }
+ ]
+}
diff --git a/test cases/failing/23 rel testdir/test.json b/test cases/failing/23 rel testdir/test.json
new file mode 100644
index 0000000..ba983ab
--- /dev/null
+++ b/test cases/failing/23 rel testdir/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/23 rel testdir/meson.build:4:0: ERROR: Workdir keyword argument must be an absolute path."
+ }
+ ]
+}
diff --git a/test cases/failing/24 int conversion/test.json b/test cases/failing/24 int conversion/test.json
new file mode 100644
index 0000000..e749928
--- /dev/null
+++ b/test cases/failing/24 int conversion/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/24 int conversion/meson.build:3:13: ERROR: String 'notanumber' cannot be converted to int"
+ }
+ ]
+}
diff --git a/test cases/failing/25 badlang/test.json b/test cases/failing/25 badlang/test.json
new file mode 100644
index 0000000..0b23fd7
--- /dev/null
+++ b/test cases/failing/25 badlang/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/25 badlang/meson.build:3:0: ERROR: Tried to use unknown language \"nonexisting\"."
+ }
+ ]
+}
diff --git a/test cases/failing/26 output subdir/test.json b/test cases/failing/26 output subdir/test.json
new file mode 100644
index 0000000..796468d
--- /dev/null
+++ b/test cases/failing/26 output subdir/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/26 output subdir/meson.build:3:0: ERROR: Output file name must not contain a subdirectory."
+ }
+ ]
+}
diff --git a/test cases/failing/27 noprog use/test.json b/test cases/failing/27 noprog use/test.json
new file mode 100644
index 0000000..b84562e
--- /dev/null
+++ b/test cases/failing/27 noprog use/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/27 noprog use/meson.build:5:0: ERROR: Tried to use not-found external program in \"command\""
+ }
+ ]
+}
diff --git a/test cases/failing/28 no crossprop/test.json b/test cases/failing/28 no crossprop/test.json
new file mode 100644
index 0000000..a186a68
--- /dev/null
+++ b/test cases/failing/28 no crossprop/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/28 no crossprop/meson.build:3:0: ERROR: Unknown cross property: nonexisting."
+ }
+ ]
+}
diff --git a/test cases/failing/29 nested ternary/test.json b/test cases/failing/29 nested ternary/test.json
new file mode 100644
index 0000000..ba05013
--- /dev/null
+++ b/test cases/failing/29 nested ternary/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/29 nested ternary/meson.build:3:12: ERROR: Nested ternary operators are not allowed."
+ }
+ ]
+}
diff --git a/test cases/failing/3 missing subdir/test.json b/test cases/failing/3 missing subdir/test.json
new file mode 100644
index 0000000..562de25
--- /dev/null
+++ b/test cases/failing/3 missing subdir/test.json
@@ -0,0 +1,9 @@
+{
+ "stdout": [
+ {
+ "comment": "'missing/meson.build' gets transformed with os.path.sep separators",
+ "match": "re",
+ "line": "test cases/failing/3 missing subdir/meson\\.build:3:0: ERROR: Non\\-existent build file 'missing[\\\\/]meson\\.build'"
+ }
+ ]
+}
diff --git a/test cases/failing/30 invalid man extension/test.json b/test cases/failing/30 invalid man extension/test.json
new file mode 100644
index 0000000..3f77a04
--- /dev/null
+++ b/test cases/failing/30 invalid man extension/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/30 invalid man extension/meson.build:2:0: ERROR: Man file must have a file extension of a number between 1 and 8"
+ }
+ ]
+}
diff --git a/test cases/failing/31 no man extension/test.json b/test cases/failing/31 no man extension/test.json
new file mode 100644
index 0000000..6e1f542
--- /dev/null
+++ b/test cases/failing/31 no man extension/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/31 no man extension/meson.build:2:0: ERROR: Man file must have a file extension of a number between 1 and 8"
+ }
+ ]
+}
diff --git a/test cases/failing/32 exe static shared/meson.build b/test cases/failing/32 exe static shared/meson.build
index b102764..2ae5125 100644
--- a/test cases/failing/32 exe static shared/meson.build
+++ b/test cases/failing/32 exe static shared/meson.build
@@ -2,7 +2,7 @@ project('statchain', 'c')
host_system = host_machine.system()
if host_system == 'windows' or host_system == 'darwin'
- error('Test only fails on Linux and BSD')
+ error('MESON_SKIP_TEST test only fails on Linux and BSD')
endif
statlib = static_library('stat', 'stat.c', pic : false)
diff --git a/test cases/failing/32 exe static shared/test.json b/test cases/failing/32 exe static shared/test.json
new file mode 100644
index 0000000..51d3804
--- /dev/null
+++ b/test cases/failing/32 exe static shared/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/32 exe static shared/meson.build:9:0: ERROR: Can't link non-PIC static library 'stat' into shared library 'shr2'. Use the 'pic' option to static_library to build with PIC."
+ }
+ ]
+}
diff --git a/test cases/failing/33 non-root subproject/test.json b/test cases/failing/33 non-root subproject/test.json
new file mode 100644
index 0000000..a14cece
--- /dev/null
+++ b/test cases/failing/33 non-root subproject/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/33 non-root subproject/some/meson.build:1:0: ERROR: Subproject directory not found and someproj.wrap file not found"
+ }
+ ]
+}
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
new file mode 100644
index 0000000..3cf35f5
--- /dev/null
+++ b/test cases/failing/34 dependency not-required then required/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "match": "re",
+ "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/35 project argument after target/test.json b/test cases/failing/35 project argument after target/test.json
new file mode 100644
index 0000000..f5efd9b
--- /dev/null
+++ b/test cases/failing/35 project argument after target/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/35 project argument after target/meson.build:7:0: ERROR: Tried to use 'add_project_arguments' after a build target has been declared."
+ }
+ ]
+}
diff --git a/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build b/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build
index 54d434c..874b581 100644
--- a/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build
+++ b/test cases/failing/36 pkgconfig dependency impossible conditions/meson.build
@@ -1,3 +1,7 @@
project('impossible-dep-test', 'c', version : '1.0')
+if not dependency('zlib', required: false).found()
+ error('MESON_SKIP_TEST test requires zlib')
+endif
+
dependency('zlib', version : ['>=1.0', '<1.0'])
diff --git a/test cases/failing/37 has function external dependency/test.json b/test cases/failing/37 has function external dependency/test.json
new file mode 100644
index 0000000..81d6f91
--- /dev/null
+++ b/test cases/failing/37 has function external dependency/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/37 has function external dependency/meson.build:8:3: ERROR: Dependencies must be external dependencies"
+ }
+ ]
+}
diff --git a/test cases/failing/38 libdir must be inside prefix/test.json b/test cases/failing/38 libdir must be inside prefix/test.json
index 1cd893c..d9256d1 100644
--- a/test cases/failing/38 libdir must be inside prefix/test.json
+++ b/test cases/failing/38 libdir must be inside prefix/test.json
@@ -1,3 +1,10 @@
{
- "do_not_set_opts": ["libdir"]
+ "do_not_set_opts": [
+ "libdir"
+ ],
+ "stdout": [
+ {
+ "line": "test cases/failing/38 libdir must be inside prefix/meson.build:1:0: ERROR: The value of the 'libdir' option is '/opt/lib' which must be a subdir of the prefix '/usr'."
+ }
+ ]
}
diff --git a/test cases/failing/39 prefix absolute/test.json b/test cases/failing/39 prefix absolute/test.json
index 4e0f6cd..2770243 100644
--- a/test cases/failing/39 prefix absolute/test.json
+++ b/test cases/failing/39 prefix absolute/test.json
@@ -1,3 +1,11 @@
{
- "do_not_set_opts": ["prefix"]
+ "do_not_set_opts": [
+ "prefix"
+ ],
+ "stdout": [
+ {
+ "comment": "literal 'some/path/notabs' appears in output, irrespective of os.path.sep, as that's the prefix",
+ "line": "test cases/failing/39 prefix absolute/meson.build:1:0: ERROR: prefix value 'some/path/notabs' must be an absolute path"
+ }
+ ]
}
diff --git a/test cases/failing/4 missing meson.build/test.json b/test cases/failing/4 missing meson.build/test.json
new file mode 100644
index 0000000..3857090
--- /dev/null
+++ b/test cases/failing/4 missing meson.build/test.json
@@ -0,0 +1,9 @@
+{
+ "stdout": [
+ {
+ "match": "re",
+ "comment": "'subdir/meson.build' gets transformed with os.path.sep separators",
+ "line": "test cases/failing/4 missing meson\\.build/meson\\.build:3:0: ERROR: Non\\-existent build file 'subdir[\\\\/]meson\\.build'"
+ }
+ ]
+}
diff --git a/test cases/failing/40 kwarg assign/test.json b/test cases/failing/40 kwarg assign/test.json
new file mode 100644
index 0000000..671eb3f
--- /dev/null
+++ b/test cases/failing/40 kwarg assign/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/40 kwarg assign/meson.build:3:0: ERROR: Tried to assign values inside an argument list."
+ }
+ ]
+}
diff --git a/test cases/failing/41 custom target plainname many inputs/test.json b/test cases/failing/41 custom target plainname many inputs/test.json
new file mode 100644
index 0000000..8c15cda
--- /dev/null
+++ b/test cases/failing/41 custom target plainname many inputs/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/41 custom target plainname many inputs/meson.build:5:0: ERROR: Output cannot contain @PLAINNAME@ or @BASENAME@ when there is more than one input (we can't know which to use)"
+ }
+ ]
+}
diff --git a/test cases/failing/42 custom target outputs not matching install_dirs/meson.build b/test cases/failing/42 custom target outputs not matching install_dirs/meson.build
index 45bd7b3..765e237 100644
--- a/test cases/failing/42 custom target outputs not matching install_dirs/meson.build
+++ b/test cases/failing/42 custom target outputs not matching install_dirs/meson.build
@@ -3,7 +3,7 @@ project('outputs not matching install_dirs', 'c')
gen = find_program('generator.py')
if meson.backend() != 'ninja'
- error('Failing manually, test is only for the ninja backend')
+ error('MESON_SKIP_TEST test is only for the ninja backend')
endif
custom_target('too-few-install-dirs',
diff --git a/test cases/failing/42 custom target outputs not matching install_dirs/test.json b/test cases/failing/42 custom target outputs not matching install_dirs/test.json
index e59cb9f..f9e2ba7 100644
--- a/test cases/failing/42 custom target outputs not matching install_dirs/test.json
+++ b/test cases/failing/42 custom target outputs not matching install_dirs/test.json
@@ -1,10 +1,33 @@
{
"installed": [
- {"type": "file", "file": "usr/include/diff.h"},
- {"type": "file", "file": "usr/include/first.h"},
- {"type": "file", "file": "usr/bin/diff.sh"},
- {"type": "file", "file": "usr/bin/second.sh"},
- {"type": "file", "file": "opt/same.h"},
- {"type": "file", "file": "opt/same.sh"}
+ {
+ "type": "file",
+ "file": "usr/include/diff.h"
+ },
+ {
+ "type": "file",
+ "file": "usr/include/first.h"
+ },
+ {
+ "type": "file",
+ "file": "usr/bin/diff.sh"
+ },
+ {
+ "type": "file",
+ "file": "usr/bin/second.sh"
+ },
+ {
+ "type": "file",
+ "file": "opt/same.h"
+ },
+ {
+ "type": "file",
+ "file": "opt/same.sh"
+ }
+ ],
+ "stdout": [
+ {
+ "line": "ERROR: Target 'too-few-install-dirs' has 3 outputs: ['toofew.h', 'toofew.c', 'toofew.sh'], but only 2 \"install_dir\"s were found."
+ }
]
}
diff --git a/test cases/failing/43 project name colon/test.json b/test cases/failing/43 project name colon/test.json
new file mode 100644
index 0000000..7a55574
--- /dev/null
+++ b/test cases/failing/43 project name colon/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/43 project name colon/meson.build:1:0: ERROR: Project name 'name with :' must not contain ':'"
+ }
+ ]
+}
diff --git a/test cases/failing/44 abs subdir/test.json b/test cases/failing/44 abs subdir/test.json
new file mode 100644
index 0000000..0aa56f6
--- /dev/null
+++ b/test cases/failing/44 abs subdir/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/44 abs subdir/meson.build:5:0: ERROR: Subdir argument must be a relative path."
+ }
+ ]
+}
diff --git a/test cases/failing/45 abspath to srcdir/test.json b/test cases/failing/45 abspath to srcdir/test.json
new file mode 100644
index 0000000..b6a87fe
--- /dev/null
+++ b/test cases/failing/45 abspath to srcdir/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/45 abspath to srcdir/meson.build:3:0: ERROR: Tried to form an absolute path to a source dir. You should not do that but use relative paths instead."
+ }
+ ]
+}
diff --git a/test cases/failing/46 pkgconfig variables reserved/test.json b/test cases/failing/46 pkgconfig variables reserved/test.json
new file mode 100644
index 0000000..b92ee17
--- /dev/null
+++ b/test cases/failing/46 pkgconfig variables reserved/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/46 pkgconfig variables reserved/meson.build:8:5: ERROR: Variable \"prefix\" is reserved"
+ }
+ ]
+}
diff --git a/test cases/failing/47 pkgconfig variables zero length/test.json b/test cases/failing/47 pkgconfig variables zero length/test.json
new file mode 100644
index 0000000..097fee1
--- /dev/null
+++ b/test cases/failing/47 pkgconfig variables zero length/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/47 pkgconfig variables zero length/meson.build:8:5: ERROR: Invalid variable \"=value\". Variables must be in 'name=value' format"
+ }
+ ]
+}
diff --git a/test cases/failing/48 pkgconfig variables zero length value/test.json b/test cases/failing/48 pkgconfig variables zero length value/test.json
new file mode 100644
index 0000000..50a35ce
--- /dev/null
+++ b/test cases/failing/48 pkgconfig variables zero length value/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/48 pkgconfig variables zero length value/meson.build:8:5: ERROR: Invalid variable \"key=\". Variables must be in 'name=value' format"
+ }
+ ]
+}
diff --git a/test cases/failing/49 pkgconfig variables not key value/test.json b/test cases/failing/49 pkgconfig variables not key value/test.json
new file mode 100644
index 0000000..cf07e62
--- /dev/null
+++ b/test cases/failing/49 pkgconfig variables not key value/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/49 pkgconfig variables not key value/meson.build:8:5: ERROR: Invalid variable \"this_should_be_key_value\". Variables must be in 'name=value' format"
+ }
+ ]
+}
diff --git a/test cases/failing/5 misplaced option/test.json b/test cases/failing/5 misplaced option/test.json
new file mode 100644
index 0000000..12afdf0
--- /dev/null
+++ b/test cases/failing/5 misplaced option/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/5 misplaced option/meson.build:3:0: ERROR: Tried to call option() in build description file. All options must be in the option file."
+ }
+ ]
+}
diff --git a/test cases/failing/50 executable comparison/test.json b/test cases/failing/50 executable comparison/test.json
new file mode 100644
index 0000000..585b382
--- /dev/null
+++ b/test cases/failing/50 executable comparison/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/50 executable comparison/meson.build:6:0: ERROR: exe1 can only be compared for equality."
+ }
+ ]
+}
diff --git a/test cases/failing/51 inconsistent comparison/test.json b/test cases/failing/51 inconsistent comparison/test.json
new file mode 100644
index 0000000..5867f0a
--- /dev/null
+++ b/test cases/failing/51 inconsistent comparison/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/51 inconsistent comparison/meson.build:5:0: ERROR: Values of different types (list, str) cannot be compared using <."
+ }
+ ]
+}
diff --git a/test cases/failing/52 slashname/test.json b/test cases/failing/52 slashname/test.json
new file mode 100644
index 0000000..180400a
--- /dev/null
+++ b/test cases/failing/52 slashname/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/52 slashname/meson.build:11:0: ERROR: Problem encountered: Re-enable me once slash in name is finally prohibited."
+ }
+ ]
+}
diff --git a/test cases/failing/53 reserved meson prefix/test.json b/test cases/failing/53 reserved meson prefix/test.json
new file mode 100644
index 0000000..502d96a
--- /dev/null
+++ b/test cases/failing/53 reserved meson prefix/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/53 reserved meson prefix/meson.build:3:0: ERROR: The \"meson-\" prefix is reserved and cannot be used for top-level subdir()."
+ }
+ ]
+}
diff --git a/test cases/failing/54 wrong shared crate type/meson.build b/test cases/failing/54 wrong shared crate type/meson.build
index 69ac3da..b9fcad4 100644
--- a/test cases/failing/54 wrong shared crate type/meson.build
+++ b/test cases/failing/54 wrong shared crate type/meson.build
@@ -1,3 +1,7 @@
-project('test', 'rust')
+project('test')
+
+if not add_languages('rust', required: false)
+ error('MESON_SKIP_TEST test requires rust compiler')
+endif
shared_library('test', 'foo.rs', rust_crate_type : 'staticlib')
diff --git a/test cases/failing/54 wrong shared crate type/test.json b/test cases/failing/54 wrong shared crate type/test.json
new file mode 100644
index 0000000..5cced6f
--- /dev/null
+++ b/test cases/failing/54 wrong shared crate type/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/54 wrong shared crate type/meson.build:7:0: ERROR: Crate type \"staticlib\" invalid for dynamic libraries; must be \"dylib\" or \"cdylib\""
+ }
+ ]
+}
diff --git a/test cases/failing/55 wrong static crate type/meson.build b/test cases/failing/55 wrong static crate type/meson.build
index c094613..109907f 100644
--- a/test cases/failing/55 wrong static crate type/meson.build
+++ b/test cases/failing/55 wrong static crate type/meson.build
@@ -1,3 +1,7 @@
-project('test', 'rust')
+project('test')
+
+if not add_languages('rust', required: false)
+ error('MESON_SKIP_TEST test requires rust compiler')
+endif
static_library('test', 'foo.rs', rust_crate_type : 'cdylib')
diff --git a/test cases/failing/55 wrong static crate type/test.json b/test cases/failing/55 wrong static crate type/test.json
new file mode 100644
index 0000000..7073f7b
--- /dev/null
+++ b/test cases/failing/55 wrong static crate type/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/55 wrong static crate type/meson.build:7:0: ERROR: Crate type \"cdylib\" invalid for static libraries; must be \"rlib\" or \"staticlib\""
+ }
+ ]
+}
diff --git a/test cases/failing/56 or on new line/test.json b/test cases/failing/56 or on new line/test.json
new file mode 100644
index 0000000..c55cee6
--- /dev/null
+++ b/test cases/failing/56 or on new line/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/56 or on new line/meson.build:4:8: ERROR: Invalid or clause."
+ }
+ ]
+}
diff --git a/test cases/failing/57 kwarg in module/test.json b/test cases/failing/57 kwarg in module/test.json
new file mode 100644
index 0000000..cafb3ab
--- /dev/null
+++ b/test cases/failing/57 kwarg in module/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/57 kwarg in module/meson.build:3:0: ERROR: Function does not take keyword arguments."
+ }
+ ]
+}
diff --git a/test cases/failing/58 link with executable/test.json b/test cases/failing/58 link with executable/test.json
new file mode 100644
index 0000000..d3975c1
--- /dev/null
+++ b/test cases/failing/58 link with executable/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/58 link with executable/meson.build:4:0: ERROR: Link target 'prog' is not linkable."
+ }
+ ]
+}
diff --git a/test cases/failing/59 assign custom target index/test.json b/test cases/failing/59 assign custom target index/test.json
new file mode 100644
index 0000000..07ecb91
--- /dev/null
+++ b/test cases/failing/59 assign custom target index/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/59 assign custom target index/meson.build:24:0: ERROR: Assignment target must be an id."
+ }
+ ]
+}
diff --git a/test cases/failing/6 missing incdir/test.json b/test cases/failing/6 missing incdir/test.json
new file mode 100644
index 0000000..172d8a9
--- /dev/null
+++ b/test cases/failing/6 missing incdir/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/6 missing incdir/meson.build:3:0: ERROR: Include dir nosuchdir does not exist."
+ }
+ ]
+}
diff --git a/test cases/failing/60 getoption prefix/test.json b/test cases/failing/60 getoption prefix/test.json
new file mode 100644
index 0000000..03bf419
--- /dev/null
+++ b/test cases/failing/60 getoption prefix/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/60 getoption prefix/meson.build:5:0: ERROR: Having a colon in option name is forbidden, projects are not allowed to directly access options of other subprojects."
+ }
+ ]
+}
diff --git a/test cases/failing/61 bad option argument/test.json b/test cases/failing/61 bad option argument/test.json
new file mode 100644
index 0000000..4002005
--- /dev/null
+++ b/test cases/failing/61 bad option argument/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/61 bad option argument/meson_options.txt:1:0: ERROR: Invalid kwargs for option \"name\": \"vaule\""
+ }
+ ]
+}
diff --git a/test cases/failing/62 subproj filegrab/test.json b/test cases/failing/62 subproj filegrab/test.json
new file mode 100644
index 0000000..dd0d7bb
--- /dev/null
+++ b/test cases/failing/62 subproj filegrab/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/62 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c from a different subproject."
+ }
+ ]
+}
diff --git a/test cases/failing/63 grab subproj/test.json b/test cases/failing/63 grab subproj/test.json
new file mode 100644
index 0000000..8147905
--- /dev/null
+++ b/test cases/failing/63 grab subproj/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/63 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a different subproject."
+ }
+ ]
+}
diff --git a/test cases/failing/64 grab sibling/test.json b/test cases/failing/64 grab sibling/test.json
new file mode 100644
index 0000000..1604d47
--- /dev/null
+++ b/test cases/failing/64 grab sibling/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/64 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c from a different subproject."
+ }
+ ]
+}
diff --git a/test cases/failing/65 string as link target/test.json b/test cases/failing/65 string as link target/test.json
new file mode 100644
index 0000000..e212482
--- /dev/null
+++ b/test cases/failing/65 string as link target/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/65 string as link target/meson.build:2:0: ERROR: '' is not a target."
+ }
+ ]
+}
diff --git a/test cases/failing/66 dependency not-found and required/test.json b/test cases/failing/66 dependency not-found and required/test.json
new file mode 100644
index 0000000..5b13316
--- /dev/null
+++ b/test cases/failing/66 dependency not-found and required/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/66 dependency not-found and required/meson.build:2:0: ERROR: Dependency is both required and not-found"
+ }
+ ]
+}
diff --git a/test cases/failing/68 wrong boost module/meson.build b/test cases/failing/68 wrong boost module/meson.build
index 7fb3a40..937e587 100644
--- a/test cases/failing/68 wrong boost module/meson.build
+++ b/test cases/failing/68 wrong boost module/meson.build
@@ -1,5 +1,9 @@
project('boosttest', 'cpp',
default_options : ['cpp_std=c++11'])
+if not dependency('boost', required: false).found()
+ error('MESON_SKIP_TEST test requires boost')
+endif
+
# abc doesn't exist
linkdep = dependency('boost', modules : ['thread', 'system', 'test', 'abc'])
diff --git a/test cases/failing/68 wrong boost module/test.json b/test cases/failing/68 wrong boost module/test.json
new file mode 100644
index 0000000..9ef1b0f
--- /dev/null
+++ b/test cases/failing/68 wrong boost module/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/68 wrong boost module/meson.build:9:0: ERROR: Dependency \"boost\" not found"
+ }
+ ]
+}
diff --git a/test cases/failing/69 install_data rename bad size/test.json b/test cases/failing/69 install_data rename bad size/test.json
new file mode 100644
index 0000000..1329fec
--- /dev/null
+++ b/test cases/failing/69 install_data rename bad size/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/69 install_data rename bad size/meson.build:3:0: ERROR: Size of rename argument is different from number of sources"
+ }
+ ]
+}
diff --git a/test cases/failing/7 go to subproject/test.json b/test cases/failing/7 go to subproject/test.json
new file mode 100644
index 0000000..c254757
--- /dev/null
+++ b/test cases/failing/7 go to subproject/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/7 go to subproject/meson.build:3:0: ERROR: Must not go into subprojects dir with subdir(), use subproject() instead."
+ }
+ ]
+}
diff --git a/test cases/failing/70 skip only subdir/test.json b/test cases/failing/70 skip only subdir/test.json
new file mode 100644
index 0000000..3b40b66
--- /dev/null
+++ b/test cases/failing/70 skip only subdir/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/70 skip only subdir/meson.build:8:0: ERROR: File main.cpp does not exist."
+ }
+ ]
+}
diff --git a/test cases/failing/71 dual override/test.json b/test cases/failing/71 dual override/test.json
new file mode 100644
index 0000000..66409e6
--- /dev/null
+++ b/test cases/failing/71 dual override/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/71 dual override/meson.build:5:6: ERROR: Tried to override executable \"override\" which has already been overridden."
+ }
+ ]
+}
diff --git a/test cases/failing/72 override used/test.json b/test cases/failing/72 override used/test.json
new file mode 100644
index 0000000..29a58f1
--- /dev/null
+++ b/test cases/failing/72 override used/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/72 override used/meson.build:5:6: ERROR: Tried to override finding of executable \"something.py\" which has already been found."
+ }
+ ]
+}
diff --git a/test cases/failing/73 run_command unclean exit/test.json b/test cases/failing/73 run_command unclean exit/test.json
new file mode 100644
index 0000000..beda187
--- /dev/null
+++ b/test cases/failing/73 run_command unclean exit/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "match": "re",
+ "line": "test cases/failing/73 run_command unclean exit/meson\\.build:4:0: ERROR: Command \".*[\\\\/]test cases[\\\\/]failing[\\\\/]73 run_command unclean exit[\\\\/]\\.[\\\\/]returncode\\.py 1\" failed with status 1\\."
+ }
+ ]
+}
diff --git a/test cases/failing/74 int literal leading zero/test.json b/test cases/failing/74 int literal leading zero/test.json
new file mode 100644
index 0000000..78a735e
--- /dev/null
+++ b/test cases/failing/74 int literal leading zero/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "comment": "this error message is not very informative",
+ "line": "test cases/failing/74 int literal leading zero/meson.build:5:13: ERROR: Expecting eof got number."
+ }
+ ]
+}
diff --git a/test cases/failing/75 configuration immutable/test.json b/test cases/failing/75 configuration immutable/test.json
new file mode 100644
index 0000000..3365aae
--- /dev/null
+++ b/test cases/failing/75 configuration immutable/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/75 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used."
+ }
+ ]
+}
diff --git a/test cases/failing/76 link with shared module on osx/meson.build b/test cases/failing/76 link with shared module on osx/meson.build
index 2c714f9..bf18b36 100644
--- a/test cases/failing/76 link with shared module on osx/meson.build
+++ b/test cases/failing/76 link with shared module on osx/meson.build
@@ -1,7 +1,7 @@
project('link with shared module', 'c')
if host_machine.system() != 'darwin'
- error('Test only fails on OSX')
+ error('MESON_SKIP_TEST test only fails on OSX')
endif
m = shared_module('mymodule', 'module.c')
diff --git a/test cases/failing/76 link with shared module on osx/test.json b/test cases/failing/76 link with shared module on osx/test.json
new file mode 100644
index 0000000..4e2856f
--- /dev/null
+++ b/test cases/failing/76 link with shared module on osx/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/76 link with shared module on osx/meson.build:8:0: ERROR: target links against shared modules."
+ }
+ ]
+}
diff --git a/test cases/failing/77 non ascii in ascii encoded configure file/test.json b/test cases/failing/77 non ascii in ascii encoded configure file/test.json
new file mode 100644
index 0000000..e35b95b
--- /dev/null
+++ b/test cases/failing/77 non ascii in ascii encoded configure file/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "match": "re",
+ "line": "test cases/failing/77 non ascii in ascii encoded configure file/meson\\.build:5:0: ERROR: Could not write output file .*[\\\\/]config9\\.h: 'ascii' codec can't encode character '\\\\u0434' in position 17: ordinal not in range\\(128\\)"
+ }
+ ]
+}
diff --git a/test cases/failing/78 subproj dependency not-found and required/test.json b/test cases/failing/78 subproj dependency not-found and required/test.json
new file mode 100644
index 0000000..534b4f4
--- /dev/null
+++ b/test cases/failing/78 subproj dependency not-found and required/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/78 subproj dependency not-found and required/meson.build:2:0: ERROR: Subproject directory not found and missing.wrap file not found"
+ }
+ ]
+}
diff --git a/test cases/failing/79 unfound run/test.json b/test cases/failing/79 unfound run/test.json
new file mode 100644
index 0000000..6baafc0
--- /dev/null
+++ b/test cases/failing/79 unfound run/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/79 unfound run/meson.build:4:0: ERROR: Tried to use non-existing executable 'nonexisting_prog'"
+ }
+ ]
+}
diff --git a/test cases/failing/8 recursive/test.json b/test cases/failing/8 recursive/test.json
new file mode 100644
index 0000000..b4c964c
--- /dev/null
+++ b/test cases/failing/8 recursive/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/8 recursive/subprojects/b/meson.build:3:0: ERROR: Recursive include of subprojects: a => b => a."
+ }
+ ]
+}
diff --git a/test cases/failing/80 framework dependency with version/meson.build b/test cases/failing/80 framework dependency with version/meson.build
index 1ead388..b7e04ba 100644
--- a/test cases/failing/80 framework dependency with version/meson.build
+++ b/test cases/failing/80 framework dependency with version/meson.build
@@ -1,4 +1,8 @@
project('framework dependency with version', 'c')
+
+if host_machine.system() != 'darwin'
+ error('MESON_SKIP_TEST test only applicable on darwin')
+endif
+
# do individual frameworks have a meaningful version to test? And multiple frameworks might be listed...
-# otherwise we're not on OSX and this will definitely fail
dep = dependency('appleframeworks', modules: 'foundation', version: '>0')
diff --git a/test cases/failing/80 framework dependency with version/test.json b/test cases/failing/80 framework dependency with version/test.json
new file mode 100644
index 0000000..5cbc129
--- /dev/null
+++ b/test cases/failing/80 framework dependency with version/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/80 framework dependency with version/meson.build:8:0: ERROR: Unknown version of dependency 'appleframeworks', but need ['>0']."
+ }
+ ]
+}
diff --git a/test cases/failing/81 override exe config/test.json b/test cases/failing/81 override exe config/test.json
new file mode 100644
index 0000000..f19785b
--- /dev/null
+++ b/test cases/failing/81 override exe config/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/81 override exe config/meson.build:6:0: ERROR: Program 'bar' was overridden with the compiled executable 'foo' and therefore cannot be used during configuration"
+ }
+ ]
+}
diff --git a/test cases/failing/82 gl dependency with version/meson.build b/test cases/failing/82 gl dependency with version/meson.build
index 3014d43..0127093 100644
--- a/test cases/failing/82 gl dependency with version/meson.build
+++ b/test cases/failing/82 gl dependency with version/meson.build
@@ -2,7 +2,7 @@ project('gl dependency with version', 'c')
host_system = host_machine.system()
if host_system != 'windows' and host_system != 'darwin'
- error('Test only fails on Windows and OSX')
+ error('MESON_SKIP_TEST: test only fails on Windows and OSX')
endif
# gl dependency found via system method doesn't have a meaningful version to check
diff --git a/test cases/failing/82 gl dependency with version/test.json b/test cases/failing/82 gl dependency with version/test.json
new file mode 100644
index 0000000..2c63a2c
--- /dev/null
+++ b/test cases/failing/82 gl dependency with version/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/82 gl dependency with version/meson.build:9:0: ERROR: Unknown version of dependency 'gl', but need ['>0']."
+ }
+ ]
+}
diff --git a/test cases/failing/83 threads dependency with version/test.json b/test cases/failing/83 threads dependency with version/test.json
new file mode 100644
index 0000000..b131be4
--- /dev/null
+++ b/test cases/failing/83 threads dependency with version/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/83 threads dependency with version/meson.build:3:0: ERROR: Unknown version of dependency 'threads', but need ['>0']."
+ }
+ ]
+}
diff --git a/test cases/failing/84 gtest dependency with version/meson.build b/test cases/failing/84 gtest dependency with version/meson.build
index 3d90994..b43a047 100644
--- a/test cases/failing/84 gtest dependency with version/meson.build
+++ b/test cases/failing/84 gtest dependency with version/meson.build
@@ -1,3 +1,8 @@
project('gtest dependency with version', ['c', 'cpp'])
+
+if not dependency('gtest', method: 'system', required: false).found()
+ error('MESON_SKIP_TEST test requires gtest')
+endif
+
# discovering gtest version is not yet implemented
dep = dependency('gtest', method: 'system', version: '>0')
diff --git a/test cases/failing/85 dub libray/meson.build b/test cases/failing/85 dub libray/meson.build
index 5b0ccac..306d5b3 100644
--- a/test cases/failing/85 dub libray/meson.build
+++ b/test cases/failing/85 dub libray/meson.build
@@ -1,3 +1,11 @@
-project('dub', 'd')
+project('dub')
+
+if not add_languages('d', required: false)
+ error('MESON_SKIP_TEST test requires D compiler')
+endif
+
+if not find_program('dub', required: false).found()
+ error('MESON_SKIP_TEST test requires dub')
+endif
dependency('dubtestproject', method: 'dub') # Not library (none)
diff --git a/test cases/failing/85 dub libray/test.json b/test cases/failing/85 dub libray/test.json
new file mode 100644
index 0000000..a8b3e28
--- /dev/null
+++ b/test cases/failing/85 dub libray/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/85 dub libray/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found"
+ }
+ ]
+}
diff --git a/test cases/failing/86 dub executable/meson.build b/test cases/failing/86 dub executable/meson.build
index 63fd631..9a134ea 100644
--- a/test cases/failing/86 dub executable/meson.build
+++ b/test cases/failing/86 dub executable/meson.build
@@ -1,3 +1,11 @@
-project('dub', 'd')
+project('dub')
+
+if not add_languages('d', required: false)
+ error('MESON_SKIP_TEST test requires D compiler')
+endif
+
+if not find_program('dub', required: false).found()
+ error('MESON_SKIP_TEST test requires dub')
+endif
dependency('dubtestproject:test1', method: 'dub') # Not library (executable)
diff --git a/test cases/failing/86 dub executable/test.json b/test cases/failing/86 dub executable/test.json
new file mode 100644
index 0000000..f9944af
--- /dev/null
+++ b/test cases/failing/86 dub executable/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/86 dub executable/meson.build:11:0: ERROR: Dependency \"dubtestproject:test1\" not found"
+ }
+ ]
+}
diff --git a/test cases/failing/87 dub compiler/meson.build b/test cases/failing/87 dub compiler/meson.build
index c93ccbc..36f1849 100644
--- a/test cases/failing/87 dub compiler/meson.build
+++ b/test cases/failing/87 dub compiler/meson.build
@@ -1,4 +1,8 @@
-project('dub', 'd')
+project('dub')
+
+if not add_languages('d', required: false)
+ error('MESON_SKIP_TEST test requires D compiler')
+endif
if meson.get_compiler('d').get_id() == 'dmd'
if host_machine.system() == 'windows' or host_machine.system() == 'cygwin'
@@ -6,4 +10,8 @@ if meson.get_compiler('d').get_id() == 'dmd'
endif
endif
+if not find_program('dub', required: false).found()
+ error('MESON_SKIP_TEST test requires dub')
+endif
+
dependency('dubtestproject:test2', method: 'dub') # Compiler mismatch
diff --git a/test cases/failing/87 dub compiler/test.json b/test cases/failing/87 dub compiler/test.json
index acb7da8..f28312f 100644
--- a/test cases/failing/87 dub compiler/test.json
+++ b/test cases/failing/87 dub compiler/test.json
@@ -2,8 +2,18 @@
"matrix": {
"options": {
"warning_level": [
- { "val": "1", "skip_on_env": [ "SINGLE_DUB_COMPILER" ] }
+ {
+ "val": "1",
+ "skip_on_env": [
+ "SINGLE_DUB_COMPILER"
+ ]
+ }
]
}
- }
+ },
+ "stdout": [
+ {
+ "line": "test cases/failing/87 dub compiler/meson.build:17:0: ERROR: Dependency \"dubtestproject:test2\" not found"
+ }
+ ]
}
diff --git a/test cases/failing/88 subproj not-found dep/test.json b/test cases/failing/88 subproj not-found dep/test.json
new file mode 100644
index 0000000..a1c4231
--- /dev/null
+++ b/test cases/failing/88 subproj not-found dep/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/88 subproj not-found dep/meson.build:2:0: ERROR: Could not find dependency notfound_dep in subproject somesubproj"
+ }
+ ]
+}
diff --git a/test cases/failing/89 invalid configure file/test.json b/test cases/failing/89 invalid configure file/test.json
new file mode 100644
index 0000000..921ce61
--- /dev/null
+++ b/test cases/failing/89 invalid configure file/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/89 invalid configure file/meson.build:3:0: ERROR: \"install_dir\" must be specified when \"install\" in a configure_file is true"
+ }
+ ]
+}
diff --git a/test cases/failing/9 missing extra file/test.json b/test cases/failing/9 missing extra file/test.json
new file mode 100644
index 0000000..188b6a6
--- /dev/null
+++ b/test cases/failing/9 missing extra file/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/9 missing extra file/meson.build:3:0: ERROR: File missing.txt does not exist."
+ }
+ ]
+}
diff --git a/test cases/failing/90 kwarg dupe/test.json b/test cases/failing/90 kwarg dupe/test.json
new file mode 100644
index 0000000..a8df75d
--- /dev/null
+++ b/test cases/failing/90 kwarg dupe/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/90 kwarg dupe/meson.build:5:0: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry."
+ }
+ ]
+}
diff --git a/test cases/failing/91 missing pch file/test.json b/test cases/failing/91 missing pch file/test.json
new file mode 100644
index 0000000..166f627
--- /dev/null
+++ b/test cases/failing/91 missing pch file/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "comment": "literal 'pch/prog.h' from meson.build appears in output, irrespective of os.path.sep",
+ "line": "test cases/failing/91 missing pch file/meson.build:2:0: ERROR: File pch/prog.h does not exist."
+ }
+ ]
+}
diff --git a/test cases/failing/92 pch source different folder/test.json b/test cases/failing/92 pch source different folder/test.json
new file mode 100644
index 0000000..d94db50
--- /dev/null
+++ b/test cases/failing/92 pch source different folder/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/92 pch source different folder/meson.build:4:0: ERROR: PCH files must be stored in the same folder."
+ }
+ ]
+}
diff --git a/test cases/failing/93 vala without c/test.json b/test cases/failing/93 vala without c/test.json
new file mode 100644
index 0000000..6185b7e
--- /dev/null
+++ b/test cases/failing/93 vala without c/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/93 vala without c/meson.build:2:0: ERROR: Compiling Vala requires C. Add C to your project languages and rerun Meson."
+ }
+ ]
+}
diff --git a/test cases/failing/94 unknown config tool/test.json b/test cases/failing/94 unknown config tool/test.json
new file mode 100644
index 0000000..a001152
--- /dev/null
+++ b/test cases/failing/94 unknown config tool/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/94 unknown config tool/meson.build:2:0: ERROR: Dependency \"no-such-config-tool\" not found"
+ }
+ ]
+}
diff --git a/test cases/failing/95 custom target install data/test.json b/test cases/failing/95 custom target install data/test.json
new file mode 100644
index 0000000..64ef530
--- /dev/null
+++ b/test cases/failing/95 custom target install data/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/95 custom target install data/meson.build:11:0: ERROR: Argument must be string or file."
+ }
+ ]
+}
diff --git a/test cases/failing/96 add dict non string key/test.json b/test cases/failing/96 add dict non string key/test.json
new file mode 100644
index 0000000..5fd4033
--- /dev/null
+++ b/test cases/failing/96 add dict non string key/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/96 add dict non string key/meson.build:9:0: ERROR: Key must be a string"
+ }
+ ]
+}
diff --git a/test cases/failing/97 add dict duplicate keys/test.json b/test cases/failing/97 add dict duplicate keys/test.json
new file mode 100644
index 0000000..9d01551
--- /dev/null
+++ b/test cases/failing/97 add dict duplicate keys/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/97 add dict duplicate keys/meson.build:9:0: ERROR: Duplicate dictionary key: myKey"
+ }
+ ]
+}
diff --git a/test cases/failing/99 no native prop/test.json b/test cases/failing/99 no native prop/test.json
new file mode 100644
index 0000000..8c320d9
--- /dev/null
+++ b/test cases/failing/99 no native prop/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/99 no native prop/meson.build:3:0: ERROR: Unknown native property: nonexisting."
+ }
+ ]
+}
diff --git a/test cases/frameworks/21 libwmf/meson.build b/test cases/frameworks/21 libwmf/meson.build
index 6952bf7..9dbab6a 100644
--- a/test cases/frameworks/21 libwmf/meson.build
+++ b/test cases/frameworks/21 libwmf/meson.build
@@ -1,7 +1,7 @@
project('libwmf test', 'c')
wm = find_program('libwmf-config', required : false)
-if not wm.found()
+if not wm.found() or meson.is_cross_build()
error('MESON_SKIP_TEST: libwmf-config not installed')
endif
diff --git a/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c b/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c
new file mode 100644
index 0000000..ee5c5e1
--- /dev/null
+++ b/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.c
@@ -0,0 +1,124 @@
+#include "dep3.h"
+
+struct _MesonDep3
+{
+ GObject parent_instance;
+
+ gchar *msg;
+};
+
+G_DEFINE_TYPE (MesonDep3, meson_dep3, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_MSG,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+/**
+ * meson_dep3_new:
+ * @msg: The message to set.
+ *
+ * Allocates a new #MesonDep3.
+ *
+ * Returns: (transfer full): a #MesonDep3.
+ */
+MesonDep3 *
+meson_dep3_new (const gchar *msg)
+{
+ g_return_val_if_fail (msg != NULL, NULL);
+
+ return g_object_new (MESON_TYPE_DEP3,
+ "message", msg,
+ NULL);
+}
+
+static void
+meson_dep3_finalize (GObject *object)
+{
+ MesonDep3 *self = (MesonDep3 *)object;
+
+ g_clear_pointer (&self->msg, g_free);
+
+ G_OBJECT_CLASS (meson_dep3_parent_class)->finalize (object);
+}
+
+static void
+meson_dep3_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MesonDep3 *self = MESON_DEP3 (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ g_value_set_string (value, self->msg);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_dep3_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MesonDep3 *self = MESON_DEP3 (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ self->msg = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_dep3_class_init (MesonDep3Class *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meson_dep3_finalize;
+ object_class->get_property = meson_dep3_get_property;
+ object_class->set_property = meson_dep3_set_property;
+
+ gParamSpecs [PROP_MSG] =
+ g_param_spec_string ("message",
+ "Message",
+ "The message to print.",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+meson_dep3_init (MesonDep3 *self)
+{
+}
+
+/**
+ * meson_dep3_return_message:
+ * @self: a #MesonDep3.
+ *
+ * Returns the message.
+ *
+ * Returns: (transfer none): a const gchar*
+ */
+const gchar*
+meson_dep3_return_message (MesonDep3 *self)
+{
+ g_return_val_if_fail (MESON_IS_DEP3 (self), NULL);
+
+ return (const gchar*) self->msg;
+}
diff --git a/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h b/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h
new file mode 100644
index 0000000..9883d76
--- /dev/null
+++ b/test cases/frameworks/7 gnome/gir/dep1/dep3/dep3.h
@@ -0,0 +1,21 @@
+#ifndef MESON_DEP3_H
+#define MESON_DEP3_H
+
+#if !defined (MESON_TEST)
+#error "MESON_TEST not defined."
+#endif
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_DEP3 (meson_dep3_get_type())
+
+G_DECLARE_FINAL_TYPE (MesonDep3, meson_dep3, MESON, DEP3, GObject)
+
+MesonDep3 *meson_dep3_new (const gchar *msg);
+const gchar *meson_dep3_return_message (MesonDep3 *self);
+
+G_END_DECLS
+
+#endif /* MESON_DEP3_H */
diff --git a/test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build b/test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build
new file mode 100644
index 0000000..1ef7765
--- /dev/null
+++ b/test cases/frameworks/7 gnome/gir/dep1/dep3/meson.build
@@ -0,0 +1,22 @@
+dep3sources = ['dep3.c', 'dep3.h']
+
+dep3lib = shared_library(
+ 'dep3lib',
+ sources : dep3sources,
+ dependencies : gobj,
+ install : true
+)
+
+dep3gir = gnome.generate_gir(
+ dep3lib,
+ sources : dep3sources,
+ nsversion : '1.0',
+ namespace : 'MesonDep3',
+ symbol_prefix : 'meson',
+ identifier_prefix : 'Meson',
+ includes : ['GObject-2.0'],
+ install : true
+)
+
+dep3_dep = declare_dependency(link_with : dep3lib,
+ sources : [dep3gir])
diff --git a/test cases/frameworks/7 gnome/gir/dep1/meson.build b/test cases/frameworks/7 gnome/gir/dep1/meson.build
index baa0b1d..2f03ede 100644
--- a/test cases/frameworks/7 gnome/gir/dep1/meson.build
+++ b/test cases/frameworks/7 gnome/gir/dep1/meson.build
@@ -1,4 +1,5 @@
subdir('dep2')
+subdir('dep3')
dep1sources = ['dep1.c', 'dep1.h']
@@ -20,11 +21,11 @@ dep1gir = gnome.generate_gir(
symbol_prefix : 'meson',
identifier_prefix : 'Meson',
header: 'dep1.h',
- includes : ['GObject-2.0', 'MesonDep2-1.0'],
+ includes : ['GObject-2.0', 'MesonDep2-1.0', dep3gir[0]],
dependencies : [dep2_dep],
install : true
)
dep1_dep = declare_dependency(link_with : dep1lib,
- dependencies : [dep2_dep],
+ dependencies : [dep2_dep, dep3_dep],
sources : [dep1gir])
diff --git a/test cases/frameworks/7 gnome/gir/meson.build b/test cases/frameworks/7 gnome/gir/meson.build
index 36bd09c..b1e0fa1 100644
--- a/test cases/frameworks/7 gnome/gir/meson.build
+++ b/test cases/frameworks/7 gnome/gir/meson.build
@@ -45,7 +45,7 @@ gnome.generate_gir(
)
test('gobject introspection/c', girexe)
-gir_paths = ':'.join([girlib.outdir(), dep1lib.outdir(), dep2lib.outdir()])
+gir_paths = ':'.join([girlib.outdir(), dep1lib.outdir(), dep2lib.outdir(), dep3lib.outdir()])
envdata = environment()
envdata.append('GI_TYPELIB_PATH', gir_paths, separator : ':')
envdata.append('LD_LIBRARY_PATH', gir_paths)
diff --git a/test cases/frameworks/7 gnome/test.json b/test cases/frameworks/7 gnome/test.json
index e69c9f0..badf410 100644
--- a/test cases/frameworks/7 gnome/test.json
+++ b/test cases/frameworks/7 gnome/test.json
@@ -13,12 +13,16 @@
{"type": "file", "platform": "cygwin", "file": "usr/lib/libdep1lib.dll.a"},
{"type": "expr", "file": "usr/lib/?libdep2lib.so"},
{"type": "file", "platform": "cygwin", "file": "usr/lib/libdep2lib.dll.a"},
+ {"type": "expr", "file": "usr/lib/?libdep3lib.so"},
+ {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep3lib.dll.a"},
{"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"},
{"type": "file", "file": "usr/lib/girepository-1.0/MesonDep1-1.0.typelib"},
{"type": "file", "file": "usr/lib/girepository-1.0/MesonDep2-1.0.typelib"},
+ {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep3-1.0.typelib"},
{"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"},
{"type": "file", "file": "usr/share/gir-1.0/MesonDep1-1.0.gir"},
{"type": "file", "file": "usr/share/gir-1.0/MesonDep2-1.0.gir"},
+ {"type": "file", "file": "usr/share/gir-1.0/MesonDep3-1.0.gir"},
{"type": "file", "file": "usr/share/glib-2.0/schemas/com.github.meson.gschema.xml"},
{"type": "file", "file": "usr/share/simple-resources.gresource"},
{"type": "file", "file": "usr/include/enums6.h"},
diff --git a/test cases/unit/36 exe_wrapper behaviour/meson.build b/test cases/unit/36 exe_wrapper behaviour/meson.build
index 16a44d5..d0817ba 100644
--- a/test cases/unit/36 exe_wrapper behaviour/meson.build
+++ b/test cases/unit/36 exe_wrapper behaviour/meson.build
@@ -1,7 +1,7 @@
project('exe wrapper behaviour', 'c')
assert(meson.is_cross_build(), 'not setup as cross build')
-assert(meson.has_exe_wrapper(), 'exe wrapper not defined?')
+assert(meson.has_exe_wrapper(), 'exe wrapper not defined?') # intentionally not changed to can_run_host_binaries,
exe = executable('prog', 'prog.c')
diff --git a/test cases/warning/1 version for string div/test.json b/test cases/warning/1 version for string div/test.json
new file mode 100644
index 0000000..c37931a
--- /dev/null
+++ b/test cases/warning/1 version for string div/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "comment": "literal '/' appears in output, irrespective of os.path.sep, as that's the operator",
+ "line": "WARNING: Project targeting '>=0.48.0' but tried to use feature introduced in '0.49.0': / with string arguments."
+ }
+ ]
+}
diff --git a/test cases/warning/2 languages missing native/test.json b/test cases/warning/2 languages missing native/test.json
new file mode 100644
index 0000000..36da0a7
--- /dev/null
+++ b/test cases/warning/2 languages missing native/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/warning/2 languages missing native/meson.build:2: WARNING: add_languages is missing native:, assuming languages are wanted for both host and build."
+ }
+ ]
+}
diff --git a/tools/dircondenser.py b/tools/dircondenser.py
index 023c14e..0e28bec 100755
--- a/tools/dircondenser.py
+++ b/tools/dircondenser.py
@@ -74,6 +74,10 @@ def condense(dirname: str):
#print('git mv "%s" "%s"' % (old_name, new_name))
subprocess.check_call(['git', 'mv', old_name, new_name])
replacements.append((old_name, new_name))
+ # update any appearances of old_name in expected stdout in test.json
+ json = os.path.join(new_name, 'test.json')
+ if os.path.isfile(json):
+ replace_source(json, [(old_name, new_name)])
os.chdir(curdir)
replace_source('run_unittests.py', replacements)
replace_source('run_project_tests.py', replacements)