aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.pylintrc9
-rw-r--r--.travis.yml2
-rw-r--r--azure-pipelines.yml23
-rw-r--r--ci/azure-steps.yml2
-rw-r--r--cross/armclang-linux.txt35
-rw-r--r--docs/markdown/Generating-sources.md6
-rw-r--r--docs/markdown/Gnome-module.md6
-rw-r--r--docs/markdown/IDE-integration.md11
-rw-r--r--docs/markdown/Reference-manual.md24
-rw-r--r--docs/markdown/Release-notes-for-0.50.0.md6
-rw-r--r--docs/markdown/Release-notes-for-0.51.0.md2
-rw-r--r--docs/markdown/Syntax.md7
-rw-r--r--docs/markdown/Unit-tests.md35
-rw-r--r--docs/markdown/Users.md2
-rw-r--r--docs/markdown/snippets/dist-command.md10
-rw-r--r--docs/markdown/snippets/find_program_version.md9
-rw-r--r--docs/markdown/snippets/gtkdoc.md11
-rw-r--r--docs/markdown/snippets/kconfig_enhancements.md3
-rw-r--r--docs/markdown/snippets/shared_module_defs.md4
-rw-r--r--mesonbuild/ast/interpreter.py2
-rw-r--r--mesonbuild/ast/introspection.py8
-rw-r--r--mesonbuild/backend/ninjabackend.py16
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/cmake/__init__.py2
-rw-r--r--mesonbuild/cmake/generator.py129
-rw-r--r--mesonbuild/cmake/interpreter.py44
-rw-r--r--mesonbuild/cmake/traceparser.py103
-rw-r--r--mesonbuild/compilers/__init__.py2
-rw-r--r--mesonbuild/compilers/c.py1
-rw-r--r--mesonbuild/compilers/compilers.py51
-rw-r--r--mesonbuild/compilers/cpp.py1
-rw-r--r--mesonbuild/compilers/fortran.py3
-rw-r--r--mesonbuild/compilers/mixins/arm.py4
-rw-r--r--mesonbuild/compilers/mixins/clike.py18
-rw-r--r--mesonbuild/compilers/mixins/gnu.py25
-rw-r--r--mesonbuild/compilers/mixins/intel.py3
-rw-r--r--mesonbuild/compilers/mixins/pgi.py32
-rw-r--r--mesonbuild/compilers/vala.py2
-rw-r--r--mesonbuild/coredata.py22
-rw-r--r--mesonbuild/dependencies/base.py57
-rw-r--r--mesonbuild/dependencies/misc.py20
-rw-r--r--mesonbuild/environment.py1
-rw-r--r--mesonbuild/interpreter.py44
-rw-r--r--mesonbuild/interpreterbase.py21
-rw-r--r--mesonbuild/linkers.py243
-rw-r--r--mesonbuild/mdist.py (renamed from mesonbuild/scripts/dist.py)128
-rw-r--r--mesonbuild/mesonlib.py70
-rw-r--r--mesonbuild/mesonmain.py4
-rw-r--r--mesonbuild/mintro.py14
-rw-r--r--mesonbuild/modules/gnome.py26
-rw-r--r--mesonbuild/modules/unstable_kconfig.py13
-rw-r--r--mesonbuild/mtest.py33
-rw-r--r--mesonbuild/scripts/depfixer.py5
-rw-r--r--mesonbuild/wrap/wrap.py18
-rwxr-xr-xrun_project_tests.py75
-rwxr-xr-xrun_tests.py23
-rwxr-xr-xrun_unittests.py97
-rw-r--r--setup.py1
-rw-r--r--sider.yml (renamed from sideci.yml)0
-rw-r--r--test cases/cmake/10 cmake_module_path/cmake/FindSomethingLikePython.cmake24
-rw-r--r--test cases/cmake/10 cmake_module_path/meson.build17
-rw-r--r--test cases/cmake/10 generator expressions/main.cpp10
-rw-r--r--test cases/cmake/10 generator expressions/meson.build12
-rw-r--r--test cases/cmake/10 generator expressions/subprojects/cmMod/CMakeLists.txt22
-rw-r--r--test cases/cmake/10 generator expressions/subprojects/cmMod/include/cmMod.hpp31
-rw-r--r--test cases/cmake/9 header only/main.cpp10
-rw-r--r--test cases/cmake/9 header only/meson.build12
-rw-r--r--test cases/cmake/9 header only/subprojects/cmMod/CMakeLists.txt11
-rw-r--r--test cases/cmake/9 header only/subprojects/cmMod/include/cmMod.hpp19
-rw-r--r--test cases/common/122 shared module/module.c16
-rw-r--r--test cases/common/122 shared module/prog.c2
-rw-r--r--test cases/common/13 pch/c/meson.build6
-rw-r--r--test cases/common/13 pch/cpp/prog.cc3
-rw-r--r--test cases/common/13 pch/generated/meson.build6
-rw-r--r--test cases/common/13 pch/meson.build10
-rw-r--r--test cases/common/13 pch/mixed/meson.build8
-rw-r--r--test cases/common/13 pch/withIncludeDirectories/meson.build6
-rw-r--r--test cases/common/164 disabler/meson.build1
-rw-r--r--test cases/common/190 openmp/meson.build21
-rw-r--r--test cases/common/223 source set realistic example/meson.build6
-rw-r--r--test cases/common/29 find program/meson.build9
-rw-r--r--test cases/common/29 find program/print-version-with-prefix.py8
-rw-r--r--test cases/common/29 find program/print-version.py8
-rw-r--r--test cases/fortran/13 coarray/meson.build7
-rw-r--r--test cases/fortran/14 fortran links c/meson.build3
-rw-r--r--test cases/fortran/2 modules/meson.build3
-rw-r--r--test cases/fortran/6 dynamic/meson.build6
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml41
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build5
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar2/foobar-docs.sgml41
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build6
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar3/foobar-docs.sgml41
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar3/meson.build6
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar4/foobar-docs.sgml41
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar4/meson.build7
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/meson.build31
-rw-r--r--test cases/kconfig/4 load_config builddir/meson.build4
-rw-r--r--test cases/linuxlike/13 cmake dependency/cmake/FindImportedTarget.cmake13
-rw-r--r--test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonTestDep/cmMesonTestDepConfig.cmake9
-rw-r--r--test cases/linuxlike/13 cmake dependency/meson.build10
-rw-r--r--test cases/linuxlike/13 cmake dependency/setup_env.json3
-rw-r--r--test cases/linuxlike/13 cmake dependency/testFlagSet.c18
-rw-r--r--test cases/unit/55 introspection/meson.build2
-rw-r--r--test cases/windows/9 vs module defs generated/subdir/meson.build1
104 files changed, 1622 insertions, 524 deletions
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..10483d3
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,9 @@
+[MASTER]
+jobs=0
+
+[REPORTS]
+score=no
+
+[MESSAGES CONTROL]
+disable=all
+enable=unreachable \ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 8f393f1..cd78f41 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -58,7 +58,7 @@ script:
- |
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
ci_env=`bash <(curl -s https://codecov.io/env)`
- docker run $ci_env -v ${PWD}/.coverage:/root/.coverage \
+ docker run --security-opt seccomp:unconfined $ci_env -v ${PWD}/.coverage:/root/.coverage \
withgit \
/bin/sh -c "cd /root && mkdir -p tools; wget -c http://nirbheek.in/files/binaries/ninja/linux-amd64/ninja -O /root/tools/ninja; chmod +x /root/tools/ninja; CC=$CC CXX=$CXX OBJC=$CC OBJCXX=$CXX PATH=/root/tools:$PATH MESON_FIXED_NINJA=1 ./run_tests.py $RUN_TESTS_ARGS -- $MESON_ARGS && chmod -R a+rwX .coverage"
fi
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 5ec62f1..56dc4b9 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -12,6 +12,21 @@ variables:
CI: 1
jobs:
+- job: Pylint
+ pool:
+ vmImage: ubuntu-latest
+
+ steps:
+ - task: UsePythonVersion@0
+ inputs:
+ versionSpec: '3.7'
+ addToPath: true
+ - script: python -m pip install pylint
+ displayName: Install Pylint
+ - script: pylint mesonbuild
+ displayName: Lint Checks
+
+
- job: vs2015
pool:
vmImage: vs2015-win2012r2
@@ -88,7 +103,6 @@ jobs:
gccx64ninja: {}
variables:
CYGWIN_ROOT: $(System.Workfolder)\cygwin
- CYGWIN_CMAKE_LINK: http://cygwin.mirror.constant.com/x86_64/release/cmake/cmake-3.13.1-1.tar.xz
CYGWIN_MIRROR: http://cygwin.mirror.constant.com
steps:
- script: |
@@ -112,15 +126,16 @@ jobs:
python35-pip,^
vala,^
wget,^
+ cmake,^
zlib-devel
displayName: Install Dependencies
- script: |
- %CYGWIN_ROOT%\bin\bash.exe -cl "wget %CYGWIN_CMAKE_LINK% -O cmake.tar.xz"
- %CYGWIN_ROOT%\bin\bash.exe -cl "tar -xf cmake.tar.xz -C /"
- displayName: Manually install CMake 3.13.1
+ %CYGWIN_ROOT%\bin\python3.5m.exe -m pip --disable-pip-version-check install pytest-xdist
+ displayName: pip install pytest-xdist
- script: |
set BOOST_ROOT=
set PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32
+ # FIXME: we need to support systems without unversioned `python3`
cp /usr/bin/python3.5 /usr/bin/python3
env.exe -- python3 run_tests.py --backend=ninja
displayName: Run Tests
diff --git a/ci/azure-steps.yml b/ci/azure-steps.yml
index 36e6fb4..d2e984f 100644
--- a/ci/azure-steps.yml
+++ b/ci/azure-steps.yml
@@ -155,7 +155,7 @@ steps:
python --version
# Needed for running unit tests in parallel.
- python -m pip install --upgrade pytest-xdist
+ python -m pip --disable-pip-version-check install --upgrade pytest-xdist
echo ""
diff --git a/cross/armclang-linux.txt b/cross/armclang-linux.txt
new file mode 100644
index 0000000..2772d82
--- /dev/null
+++ b/cross/armclang-linux.txt
@@ -0,0 +1,35 @@
+# Using ARM compilers from Linux command line is tricky and
+# not really well documented because they want you to use
+# their IDE instead.
+#
+# First you need to do the full install with the IDE and set
+# up license files et al. This may be possible from the command
+# line.
+#
+# Then you need to do the following:
+#
+# Select toolchain by running /opt/arm/developmentstudio-2019.0/bin/select_default_toolchain
+# Armcc is only available in toolchain version 5.
+# Armclang is only available in toolchain version 6.
+# Start shell with /opt/arm/developmentstudio-2019.0/bin/suite_exec zsh
+# Now the compilers will work.
+
+[binaries]
+# we could set exe_wrapper = qemu-arm-static but to test the case
+# when cross compiled binaries can't be run we don't do that
+c = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armclang'
+#c = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler5.06u6/bin/armcc'
+#cpp = '/usr/bin/arm-linux-gnueabihf-g++'
+ar = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armar'
+#strip = '/usr/arm-linux-gnueabihf/bin/strip'
+#pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config'
+
+[properties]
+
+#c_args = ['--target=aarch64-arm-none-eabi']
+
+[host_machine]
+system = 'baremetal'
+cpu_family = 'arm'
+cpu = 'armv7' # Not sure if correct.
+endian = 'little'
diff --git a/docs/markdown/Generating-sources.md b/docs/markdown/Generating-sources.md
index fe7d7ef..e22112f 100644
--- a/docs/markdown/Generating-sources.md
+++ b/docs/markdown/Generating-sources.md
@@ -59,14 +59,14 @@ foo_c = custom_target(
output : 'foo.c',
input : 'my_gen.py',
command : [prog_python, '@INPUT@', '--code', '@OUTPUT@'],
-]
+)
foo_h = custom_target(
'foo.h',
output : 'foo.h',
input : 'my_gen.py',
command : [prog_python, '@INPUT@', '--header', '@OUTPUT@'],
-]
+)
libfoo = static_library('foo', [foo_c, foo_h])
@@ -94,7 +94,7 @@ foo_ch = custom_target(
output : ['foo.c', 'foo.h'],
input : 'my_gen.py',
command : [prog_python, '@INPUT@', '@OUTPUT@'],
-]
+)
libfoo = static_library('foo', [foo_ch])
diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md
index dcd843f..9d8029e 100644
--- a/docs/markdown/Gnome-module.md
+++ b/docs/markdown/Gnome-module.md
@@ -339,10 +339,16 @@ of the module.
* `scanobjs_args`: a list of arguments to pass to `gtkdoc-scangobj`
* `c_args`: (*Added 0.48.0*) additional compile arguments to pass
* `src_dir`: include_directories to include
+* `check`: (*Since 0.52.0*) if `true` runs `gtkdoc-check` when running unit tests.
+ Note that this has the downside of rebuilding the doc for each build, which is
+ often very slow. It usually should be enabled only in CI.
This creates a `$module-doc` target that can be ran to build docs and
normally these are only built on install.
+*Since 0.52.0* Returns a target object that can be passed as dependency to other
+targets using generated doc files (e.g. in `content_files` of another doc).
+
### gnome.gtkdoc_html_dir()
Takes as argument a module name and returns the path where that
diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md
index 21226c9..ec347d7 100644
--- a/docs/markdown/IDE-integration.md
+++ b/docs/markdown/IDE-integration.md
@@ -143,7 +143,8 @@ the `intro-buildoptions.json` file. Here is the JSON format for each option.
"description": "the description",
"type": "type ID",
"value": "value depends on type",
- "section": "section ID"
+ "section": "section ID",
+ "machine": "machine ID"
}
```
@@ -168,6 +169,13 @@ The possible values for `section` are:
- user
- test
+The `machine` key specifies the machine configuration for the option. Possible
+values are:
+
+ - any
+ - host
+ - build
+
To set the options, use the `meson configure` command.
Since Meson 0.50.0 it is also possible to get the default buildoptions
@@ -250,5 +258,6 @@ This API can also work without a build directory for the `--projectinfo` command
# Existing integrations
- [Gnome Builder](https://wiki.gnome.org/Apps/Builder)
+- [KDevelop](https://www.kdevelop.org)
- [Eclipse CDT](https://www.eclipse.org/cdt/) (experimental)
- [Meson Cmake Wrapper](https://github.com/prozum/meson-cmake-wrapper) (for cmake IDEs)
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 195c451..6be3ed7 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -131,7 +131,7 @@ This function creates a new top-level target. Like all top-level targets, this
integrates with the selected backend. For instance, with Ninja you can
run it as `ninja target_name`. This is a dummy target that does not execute any
command, but ensures that all dependencies are built. Dependencies can be any
-build target (e.g. return value of executable(), custom_target(), etc)
+build target (e.g. return value of [executable()](#executable), custom_target(), etc)
### assert()
@@ -586,7 +586,7 @@ be passed to [shared and static libraries](#library).
- `include_directories` one or more objects created with the
`include_directories` function, or, since 0.50.0, strings, which
will be transparently expanded to include directory objects
-- `install`, when set to true, this executable should be installed
+- `install`, when set to true, this executable should be installed, defaults to `false`
- `install_dir` override install directory for this file. The value is
relative to the `prefix` specified. F.ex, if you want to install
plugins into a subdir, you'd use something like this: `install_dir :
@@ -671,6 +671,14 @@ Keyword arguments are the following:
[disabler object](#disabler-object) instead of a not-found object.
*Since 0.49.0*
+- `version` *(since 0.52.0)* Specifies the required version, see
+ [`dependency()`](#dependency) for argument format. The version of the program
+ is determined by running `program_name --version` command. If stdout is empty
+ it fallbacks to stderr. If the output contains more text than simply a version
+ number, only the first occurence of numbers separated by dots is kept.
+ If the output is more complicated than that, the version checking will have to
+ be done manually using [`run_command()`](#run_command).
+
Meson will also autodetect scripts with a shebang line and run them
with the executable/interpreter specified in it both on Windows
(because the command invocator will reject the command otherwise) and
@@ -1334,6 +1342,13 @@ variables defined in the [`executable`](#executable) it is loaded by,
you will need to set the `export_dynamic` argument of the executable to
`true`.
+Supports the following extra keyword arguments:
+
+- `vs_module_defs`, *(Added 0.52.0)*, a string, a File object, or
+ Custom Target for a Microsoft module definition file for controlling
+ symbol exports, etc., on platforms where that is possible
+ (e.g. Windows).
+
**Note:** Linking to a shared module is not supported on some
platforms, notably OSX. Consider using a
[`shared_library`](#shared_library) instead, if you need to both
@@ -1779,6 +1794,7 @@ are immutable, all operations return their results as a new string.
- `is_even()` returns true if the number is even
- `is_odd()` returns true if the number is odd
+ - `to_string()` returns the value of the number as a string.
### `boolean` object
@@ -2210,7 +2226,7 @@ an external dependency with the following methods:
- sources: any compiled or static sources the dependency has
- `get_variable(cmake : str, pkgconfig : str, configtool : str,
- default_value : str, pkgconfig_define : [str, str]) *(Added in
+ default_value : str, pkgconfig_define : [str, str])` *(Added in
0.51.0)* A generic variable getter method, which repalces the
get_*type*_variable methods. This allows one to get the variable
from a dependency without knowing specifically how that dependency
@@ -2238,7 +2254,7 @@ and has the following methods:
- `path()` which returns a string pointing to the script or executable
**NOTE:** You should not need to use this method. Passing the object
- itself should work in all cases. F.ex.: `run_command(obj, arg1, arg2)`
+ itself should work in all cases. For example: `run_command(obj, arg1, arg2)`
### `environment` object
diff --git a/docs/markdown/Release-notes-for-0.50.0.md b/docs/markdown/Release-notes-for-0.50.0.md
index 44e8573..62a4b80 100644
--- a/docs/markdown/Release-notes-for-0.50.0.md
+++ b/docs/markdown/Release-notes-for-0.50.0.md
@@ -334,3 +334,9 @@ Meson now generates a `meson-info.json` file in the `meson-info` directory
to provide introspection information about the latest meson run. This file
is updated when the build configuration is changed and the build files are
(re)generated.
+
+## New kwarg `install:` for `configure_file()`
+
+Previously when using `configure_file()`, you could install the outputted file
+by setting the `install_dir:` keyword argument. Now, there is an explicit kwarg
+`install:` to enable/disable it. Omitting it will maintain the old behaviour.
diff --git a/docs/markdown/Release-notes-for-0.51.0.md b/docs/markdown/Release-notes-for-0.51.0.md
index 86b2f70..b7e441c 100644
--- a/docs/markdown/Release-notes-for-0.51.0.md
+++ b/docs/markdown/Release-notes-for-0.51.0.md
@@ -110,7 +110,7 @@ dependency you have.
```meson
dep = dependency('could_be_cmake_or_pkgconfig')
# cmake returns 'YES', pkg-config returns 'ON'
-if ['YES', 'ON'].contains(dep.get_variable(pkg-config : 'var-name', cmake : 'COP_VAR_NAME', default_value : 'NO'))
+if ['YES', 'ON'].contains(dep.get_variable(pkgconfig : 'var-name', cmake : 'COP_VAR_NAME', default_value : 'NO'))
error('Cannot build your project when dep is built with var-name support')
endif
```
diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md
index 7802b92..24d9deb 100644
--- a/docs/markdown/Syntax.md
+++ b/docs/markdown/Syntax.md
@@ -78,6 +78,13 @@ string_var = '42'
num = string_var.to_int()
```
+Numbers can be converted to a string:
+
+```meson
+int_var = 42
+string_var = int_var.to_string()
+```
+
Booleans
--
diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md
index 694c190..3c27732 100644
--- a/docs/markdown/Unit-tests.md
+++ b/docs/markdown/Unit-tests.md
@@ -71,10 +71,23 @@ The simplest thing to do is just to run all tests, which is equivalent to runnin
$ meson test
```
-You can also run only a single test by giving its name:
+### Run subsets of tests
+
+For clarity, consider the meson.build containing:
+
+```meson
+
+test('A', ..., suite: 'foo')
+test('B', ..., suite: 'foo')
+test('C', ..., suite: 'bar')
+test('D', ..., suite: 'baz')
+
+```
+
+Specify test(s) by name like:
```console
-$ meson test testname
+$ meson test A D
```
Tests belonging to a suite `suite` can be run as follows
@@ -85,6 +98,18 @@ $ meson test --suite (sub)project_name:suite
Since version *0.46*, `(sub)project_name` can be omitted if it is the top-level project.
+Multiple suites are specified like:
+
+```console
+$ meson test --suite foo --suite bar
+```
+
+NOTE: If you choose to specify both suite(s) and specific test name(s), the
+test name(s) must be contained in the suite(s). This however is redundant--
+it would be more useful to specify either specific test names or suite(s).
+
+### Other test options
+
Sometimes you need to run the tests multiple times, which is done like this:
```console
@@ -127,4 +152,8 @@ Meson will report the output produced by the failing tests along with other usef
For further information see the command line help of Meson by running `meson test -h`.
-**NOTE:** If `meson test` does not work for you, you likely have a old version of Meson. In that case you should call `mesontest` instead. If `mesontest` doesn't work either you have a very old version prior to 0.37.0 and should upgrade.
+## Legacy notes
+
+If `meson test` does not work for you, you likely have a old version of Meson.
+In that case you should call `mesontest` instead. If `mesontest` doesn't work
+either you have a very old version prior to 0.37.0 and should upgrade.
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index be11cc0..37939dc 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -8,6 +8,7 @@ If you have a project that uses Meson that you want to add to this list, please
listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [2048.cpp](https://github.com/plibither8/2048.cpp), a fully featured terminal version of the game "2048" written in C++
+ - [Aravis](https://github.com/AravisProject/aravis), a glib/gobject based library for video acquisition using Genicam cameras
- [Akira](https://github.com/akiraux/Akira), a native Linux app for UI and UX design built in Vala and Gtk
- [AQEMU](https://github.com/tobimensch/aqemu), a Qt GUI for QEMU virtual machines, since version 0.9.3
- [Arduino sample project](https://github.com/jpakkane/mesonarduino)
@@ -48,6 +49,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [Hardcode-Tray](https://github.com/bil-elmoussaoui/Hardcode-Tray), fixes hardcoded tray icons in Linux
- [HexChat](https://github.com/hexchat/hexchat), a cross-platform IRC client in C
- [IGT](https://cgit.freedesktop.org/xorg/app/intel-gpu-tools/), Linux kernel graphics driver test suite
+ - [Irssi](https://github.com/irssi/irssi), a terminal chat client in C
- [iSH](https://github.com/tbodt/ish), Linux shell for iOS
- [Janet](https://github.com/janet-lang/janet), a functional and imperative programming language and bytecode interpreter
- [json](https://github.com/nlohmann/json), JSON for Modern C++
diff --git a/docs/markdown/snippets/dist-command.md b/docs/markdown/snippets/dist-command.md
new file mode 100644
index 0000000..026b8cd
--- /dev/null
+++ b/docs/markdown/snippets/dist-command.md
@@ -0,0 +1,10 @@
+## Dist is now a top level command
+
+Previously creating a source archive could only be done with `ninja
+dist`. Starting with this release Meson provides a top level `dist`
+that can be invoked directly. It also has a command line option to
+determine which kinds of archives to create:
+
+```meson
+meson dist --formats=xztar,zip
+```
diff --git a/docs/markdown/snippets/find_program_version.md b/docs/markdown/snippets/find_program_version.md
new file mode 100644
index 0000000..04424d7
--- /dev/null
+++ b/docs/markdown/snippets/find_program_version.md
@@ -0,0 +1,9 @@
+## Version check in `find_program()`
+
+A new `version` keyword argument has been added to `find_program` to specify
+the required version. See [`dependency()`](#dependency) for argument format.
+The version of the program is determined by running `program_name --version`
+command. If stdout is empty it fallbacks to stderr. If the output contains more
+text than simply a version number, only the first occurence of numbers separated
+by dots is kept. If the output is more complicated than that, the version
+checking will have to be done manually using [`run_command()`](#run_command).
diff --git a/docs/markdown/snippets/gtkdoc.md b/docs/markdown/snippets/gtkdoc.md
new file mode 100644
index 0000000..f1f4ed4
--- /dev/null
+++ b/docs/markdown/snippets/gtkdoc.md
@@ -0,0 +1,11 @@
+## gtkdoc-check support
+
+`gnome.gtkdoc()` now has a `check` keyword argument. If `true` runs it will run
+`gtkdoc-check` when running unit tests. Note that this has the downside of
+rebuilding the doc for each build, which is often very slow. It usually should
+be enabled only in CI.
+
+## `gnome.gtkdoc()` returns target object
+
+`gnome.gtkdoc()` now returns a target object that can be passed as dependency to
+other targets using generated doc files (e.g. in `content_files` of another doc).
diff --git a/docs/markdown/snippets/kconfig_enhancements.md b/docs/markdown/snippets/kconfig_enhancements.md
new file mode 100644
index 0000000..94e3872
--- /dev/null
+++ b/docs/markdown/snippets/kconfig_enhancements.md
@@ -0,0 +1,3 @@
+## Enhancements to the kconfig module
+
+`kconfig.load()` may now accept a `configure_file()` as input file.
diff --git a/docs/markdown/snippets/shared_module_defs.md b/docs/markdown/snippets/shared_module_defs.md
new file mode 100644
index 0000000..5bc1de7
--- /dev/null
+++ b/docs/markdown/snippets/shared_module_defs.md
@@ -0,0 +1,4 @@
+## Added `vs_module_defs` to `shared_module()`
+
+Like `shared_library()`, `shared_module()` now accepts
+`vs_module_defs` argument for controlling symbol exports, etc.
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index 0e490ab..13c717b 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -325,7 +325,7 @@ class AstInterpreter(interpreterbase.InterpreterBase):
for key, val in kwargs.items():
if isinstance(val, ElementaryNode):
flattend_kwargs[key] = val.value
- elif isinstance(val, (ArrayNode, ArgumentNode)):
+ elif isinstance(val, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)):
flattend_kwargs[key] = self.flatten_args(val, include_unknown_args)
elif isinstance(val, (str, bool, int, float)) or include_unknown_args:
flattend_kwargs[key] = val
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
index 617b140..aeb0400 100644
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -158,16 +158,20 @@ class IntrospectionInterpreter(AstInterpreter):
args = self.flatten_args(args)
if not args or not isinstance(args[0], str):
return
- kwargs = self.flatten_kwargs(kwargs, True)
name = args[0]
srcqueue = [node]
+
+ # Process the soruces BEFORE flattening the kwargs, to preserve the original nodes
if 'sources' in kwargs:
- srcqueue += kwargs['sources']
+ srcqueue += mesonlib.listify(kwargs['sources'])
+
+ kwargs = self.flatten_kwargs(kwargs, True)
source_nodes = []
while srcqueue:
curr = srcqueue.pop(0)
arg_node = None
+ assert(isinstance(curr, BaseNode))
if isinstance(curr, FunctionNode):
arg_node = curr.args
elif isinstance(curr, ArrayNode):
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index b0bbbf5..b614b41 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -32,7 +32,7 @@ from .. import compilers
from ..compilers import Compiler, CompilerArgs, CCompiler, VisualStudioLikeCompiler, FortranCompiler
from ..linkers import ArLinker
from ..mesonlib import (
- File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine
+ File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine, ProgressBar
)
from ..mesonlib import get_compiler_for_source, has_path_sep
from .backends import CleanTrees
@@ -294,7 +294,7 @@ int dummy;
self.build_elements = []
self.generate_phony()
self.add_build_comment(NinjaComment('Build rules for targets'))
- for t in self.build.get_targets().values():
+ for t in ProgressBar(self.build.get_targets().values(), desc='Generating targets'):
self.generate_target(t)
self.add_build_comment(NinjaComment('Test rules'))
self.generate_tests()
@@ -883,7 +883,7 @@ int dummy;
r.write(outfile)
def write_builds(self, outfile):
- for b in self.build_elements:
+ for b in ProgressBar(self.build_elements, desc='Writing build.ninja'):
b.write(outfile)
def generate_phony(self):
@@ -2441,7 +2441,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# Add linker args for linking this target derived from 'base' build
# options passed on the command-line, in default_options, etc.
# These have the lowest priority.
- if not isinstance(target, build.StaticLibrary):
+ if isinstance(target, build.StaticLibrary):
+ commands += linker.get_base_link_args(self.get_base_options_for_target(target))
+ else:
commands += compilers.get_base_link_args(self.get_base_options_for_target(target),
linker,
isinstance(target, build.SharedModule))
@@ -2617,11 +2619,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
def generate_dist(self):
elem = NinjaBuildElement(self.all_outputs, 'meson-dist', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('DESC', 'Creating source packages')
- elem.add_item('COMMAND', self.environment.get_build_command() + [
- '--internal', 'dist',
- self.environment.source_dir,
- self.environment.build_dir,
- ] + self.environment.get_build_command())
+ elem.add_item('COMMAND', self.environment.get_build_command() + ['dist'])
elem.add_item('pool', 'console')
self.add_build(elem)
# Alias that runs the target defined above
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 2e23a59..d5814ff 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -91,7 +91,7 @@ known_build_target_kwargs = (
known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'link_language', 'pie'}
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'}
-known_shmod_kwargs = known_build_target_kwargs
+known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'}
known_stlib_kwargs = known_build_target_kwargs | {'pic'}
known_jar_kwargs = known_exe_kwargs | {'main_class'}
diff --git a/mesonbuild/cmake/__init__.py b/mesonbuild/cmake/__init__.py
index 01e1980..f9835a1 100644
--- a/mesonbuild/cmake/__init__.py
+++ b/mesonbuild/cmake/__init__.py
@@ -23,10 +23,12 @@ __all__ = [
'CMakeTarget',
'CMakeTraceLine',
'CMakeTraceParser',
+ 'parse_generator_expressions',
]
from .common import CMakeException
from .client import CMakeClient
from .executor import CMakeExecutor
+from .generator import parse_generator_expressions
from .interpreter import CMakeInterpreter
from .traceparser import CMakeTarget, CMakeTraceLine, CMakeTraceParser
diff --git a/mesonbuild/cmake/generator.py b/mesonbuild/cmake/generator.py
new file mode 100644
index 0000000..a30d2de
--- /dev/null
+++ b/mesonbuild/cmake/generator.py
@@ -0,0 +1,129 @@
+# Copyright 2019 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .. import mesonlib
+
+def parse_generator_expressions(raw: str) -> str:
+ '''Parse CMake generator expressions
+
+ Most generator expressions are simply ignored for
+ simplicety, however some are required for some common
+ use cases.
+ '''
+
+ out = '' # type: str
+ i = 0 # type: int
+
+ def equal(arg: str) -> str:
+ col_pos = arg.find(',')
+ if col_pos < 0:
+ return '0'
+ else:
+ return '1' if arg[:col_pos] == arg[col_pos + 1:] else '0'
+
+ def vers_comp(op: str, arg: str) -> str:
+ col_pos = arg.find(',')
+ if col_pos < 0:
+ return '0'
+ else:
+ return '1' if mesonlib.version_compare(arg[:col_pos], '{}{}'.format(op, arg[col_pos + 1:])) else '0'
+
+ supported = {
+ # Boolean functions
+ 'BOOL': lambda x: '0' if x.upper() in ['0', 'FALSE', 'OFF', 'N', 'NO', 'IGNORE', 'NOTFOUND'] or x.endswith('-NOTFOUND') else '1',
+ 'AND': lambda x: '1' if all([y == '1' for y in x.split(',')]) else '0',
+ 'OR': lambda x: '1' if any([y == '1' for y in x.split(',')]) else '0',
+ 'NOT': lambda x: '0' if x == '1' else '1',
+
+ '0': lambda x: '',
+ '1': lambda x: x,
+
+ # String operations
+ 'STREQUAL': equal,
+ 'EQUAL': equal,
+ 'VERSION_LESS': lambda x: vers_comp('<', x),
+ 'VERSION_GREATER': lambda x: vers_comp('>', x),
+ 'VERSION_EQUAL': lambda x: vers_comp('=', x),
+ 'VERSION_LESS_EQUAL': lambda x: vers_comp('<=', x),
+ 'VERSION_GREATER_EQUAL': lambda x: vers_comp('>=', x),
+
+ # String modification
+ 'LOWER_CASE': lambda x: x.lower(),
+ 'UPPER_CASE': lambda x: x.upper(),
+
+ # Always assume the BUILD_INTERFACE is valid.
+ # INSTALL_INTERFACE is always invalid for subprojects and
+ # it should also never appear in CMake config files, used
+ # for dependencies
+ 'INSTALL_INTERFACE': lambda x: '',
+ 'BUILD_INTERFACE': lambda x: x,
+
+ # Constants
+ 'ANGLE-R': lambda x: '>',
+ 'COMMA': lambda x: ',',
+ 'SEMICOLON': lambda x: ';',
+ }
+
+ # Recursively evaluate generator expressions
+ def eval_generator_expressions() -> str:
+ nonlocal i
+ i += 2
+
+ func = '' # type: str
+ args = '' # type: str
+ res = '' # type: str
+ exp = '' # type: str
+
+ # Determine the body of the expression
+ while i < len(raw):
+ if raw[i] == '>':
+ # End of the generator expression
+ break
+ elif i < len(raw) - 1 and raw[i] == '$' and raw[i + 1] == '<':
+ # Nested generator expression
+ exp += eval_generator_expressions()
+ else:
+ # Generator expression body
+ exp += raw[i]
+
+ i += 1
+
+ # Split the expression into a function and arguments part
+ col_pos = exp.find(':')
+ if col_pos < 0:
+ func = exp
+ else:
+ func = exp[:col_pos]
+ args = exp[col_pos + 1:]
+
+ func = func.strip()
+ args = args.strip()
+
+ # Evaluate the function
+ if func in supported:
+ res = supported[func](args)
+
+ return res
+
+ while i < len(raw):
+ if i < len(raw) - 1 and raw[i] == '$' and raw[i + 1] == '<':
+ # Generator expression detected --> try resolving it
+ out += eval_generator_expressions()
+ else:
+ # Normal string, leave unchanged
+ out += raw[i]
+
+ i += 1
+
+ return out
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 28a8488..5687ad2 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -74,8 +74,11 @@ target_type_map = {
'SHARED_LIBRARY': 'shared_library',
'EXECUTABLE': 'executable',
'OBJECT_LIBRARY': 'static_library',
+ 'INTERFACE_LIBRARY': 'header_only'
}
+target_type_requires_trace = ['INTERFACE_LIBRARY']
+
skip_targets = ['UTILITY']
blacklist_compiler_flags = [
@@ -138,6 +141,7 @@ class ConverterTarget:
self.link_with = []
self.object_libs = []
self.compile_opts = {}
+ self.public_compile_opts = []
self.pie = False
# Project default override options (c_std, cpp_std, etc.)
@@ -170,7 +174,7 @@ class ConverterTarget:
std_regex = re.compile(r'([-]{1,2}std=|/std:v?|[-]{1,2}std:)(.*)')
- def postprocess(self, output_target_map: dict, root_src_dir: str, subdir: str, install_prefix: str) -> None:
+ def postprocess(self, output_target_map: dict, root_src_dir: str, subdir: str, install_prefix: str, trace: CMakeTraceParser) -> None:
# Detect setting the C and C++ standard
for i in ['c', 'cpp']:
if i not in self.compile_opts:
@@ -194,6 +198,18 @@ class ConverterTarget:
if self.type.upper() == 'OBJECT_LIBRARY':
self.pie = True
+ # Use the CMake trace, if required
+ if self.type.upper() in target_type_requires_trace:
+ if self.name in trace.targets:
+ props = trace.targets[self.name].properies
+
+ self.includes += props.get('INTERFACE_INCLUDE_DIRECTORIES', [])
+ self.public_compile_opts += props.get('INTERFACE_COMPILE_DEFINITIONS', [])
+ self.public_compile_opts += props.get('INTERFACE_COMPILE_OPTIONS', [])
+ self.link_flags += props.get('INTERFACE_LINK_OPTIONS', [])
+ else:
+ mlog.warning('CMake: Target', mlog.bold(self.name), 'not found in CMake trace. This can lead to build errors')
+
# Fix link libraries
temp = []
for i in self.link_libraries:
@@ -584,7 +600,7 @@ class CMakeInterpreter:
for i in self.custom_targets:
i.postprocess(output_target_map, self.src_dir, self.subdir, self.build_dir)
for i in self.targets:
- i.postprocess(output_target_map, self.src_dir, self.subdir, self.install_prefix)
+ i.postprocess(output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace)
if i.type == 'OBJECT_LIBRARY':
object_libs += [i]
self.languages += [x for x in i.languages if x not in self.languages]
@@ -762,17 +778,31 @@ class CMakeInterpreter:
dep_kwargs = {
'link_args': tgt.link_flags + tgt.link_libraries,
'link_with': id_node(tgt_var),
+ 'compile_args': tgt.public_compile_opts,
'include_directories': id_node(inc_var),
}
# Generate the function nodes
- inc_node = assign(inc_var, function('include_directories', tgt.includes))
- src_node = assign(src_var, function('files', sources))
- tgt_node = assign(tgt_var, function(tgt_func, [base_name, [id_node(src_var)] + generated], tgt_kwargs))
- dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
+ node_list = []
+ if tgt_func == 'header_only':
+ del dep_kwargs['link_with']
+ inc_node = assign(inc_var, function('include_directories', tgt.includes))
+ dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
+
+ node_list = [inc_node, dep_node]
+ src_var = ''
+ tgt_var = ''
+
+ else:
+ inc_node = assign(inc_var, function('include_directories', tgt.includes))
+ src_node = assign(src_var, function('files', sources))
+ tgt_node = assign(tgt_var, function(tgt_func, [base_name, [id_node(src_var)] + generated], tgt_kwargs))
+ dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
+
+ node_list = [inc_node, src_node, tgt_node, dep_node]
# Add the nodes to the ast
- root_cb.lines += [inc_node, src_node, tgt_node, dep_node]
+ root_cb.lines += node_list
processed[tgt.name] = {'inc': inc_var, 'src': src_var, 'dep': dep_var, 'tgt': tgt_var, 'func': tgt_func}
def process_custom_target(tgt: ConverterCustomTarget) -> None:
diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py
index 4b87319..3a3f269 100644
--- a/mesonbuild/cmake/traceparser.py
+++ b/mesonbuild/cmake/traceparser.py
@@ -16,6 +16,7 @@
# or an interpreter-based tool.
from .common import CMakeException
+from .generator import parse_generator_expressions
from .. import mlog
from typing import List, Tuple, Optional
@@ -81,7 +82,11 @@ class CMakeTraceParser:
'add_custom_command': self._cmake_add_custom_command,
'add_custom_target': self._cmake_add_custom_target,
'set_property': self._cmake_set_property,
- 'set_target_properties': self._cmake_set_target_properties
+ 'set_target_properties': self._cmake_set_target_properties,
+ 'target_compile_definitions': self._cmake_target_compile_definitions,
+ 'target_compile_options': self._cmake_target_compile_options,
+ 'target_include_directories': self._cmake_target_include_directories,
+ 'target_link_options': self._cmake_target_link_options,
}
# Primary pass -- parse everything
@@ -199,16 +204,23 @@ class CMakeTraceParser:
args = list(tline.args) # Make a working copy
# Make sure the lib is imported
- if 'IMPORTED' not in args:
- return self._gen_exception('add_library', 'non imported libraries are not supported', tline)
+ if 'INTERFACE' in args:
+ args.remove('INTERFACE')
- args.remove('IMPORTED')
+ if len(args) < 1:
+ return self._gen_exception('add_library', 'interface library name not specified', tline)
- # No only look at the first two arguments (target_name and target_type) and ignore the rest
- if len(args) < 2:
- return self._gen_exception('add_library', 'requires at least 2 arguments', tline)
+ self.targets[args[0]] = CMakeTarget(args[0], 'INTERFACE', {})
+ elif 'IMPORTED' in args:
+ args.remove('IMPORTED')
- self.targets[args[0]] = CMakeTarget(args[0], args[1], {})
+ # No only look at the first two arguments (target_name and target_type) and ignore the rest
+ if len(args) < 2:
+ return self._gen_exception('add_library', 'requires at least 2 arguments', tline)
+
+ self.targets[args[0]] = CMakeTarget(args[0], args[1], {})
+ else:
+ return self._gen_exception('add_library', 'non imported / interface libraries are not supported', tline)
def _cmake_add_custom_command(self, tline: CMakeTraceLine):
# DOC: https://cmake.org/cmake/help/latest/command/add_custom_command.html
@@ -343,8 +355,8 @@ class CMakeTraceParser:
# set_property() this is not context free. There are two approaches I
# can think of, both have drawbacks:
#
- # 1. Assume that the property will be capitalized, this is convention
- # but cmake doesn't require it.
+ # 1. Assume that the property will be capitalized ([A-Z_]), this is
+ # convention but cmake doesn't require it.
# 2. Maintain a copy of the list here: https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#target-properties
#
# Neither of these is awesome for obvious reasons. I'm going to try
@@ -354,8 +366,9 @@ class CMakeTraceParser:
arglist = [] # type: List[Tuple[str, List[str]]]
name = args.pop(0)
values = []
+ prop_regex = re.compile(r'^[A-Z_]+$')
for a in args:
- if a.isupper():
+ if prop_regex.match(a):
if values:
arglist.append((name, ' '.join(values).split(';')))
name = a
@@ -372,11 +385,70 @@ class CMakeTraceParser:
self.targets[i].properies[name] = value
+ def _cmake_target_compile_definitions(self, tline: CMakeTraceLine) -> None:
+ # DOC: https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
+ self._parse_common_target_options('target_compile_definitions', 'COMPILE_DEFINITIONS', 'INTERFACE_COMPILE_DEFINITIONS', tline)
+
+ def _cmake_target_compile_options(self, tline: CMakeTraceLine) -> None:
+ # DOC: https://cmake.org/cmake/help/latest/command/target_compile_options.html
+ self._parse_common_target_options('target_compile_options', 'COMPILE_OPTIONS', 'INTERFACE_COMPILE_OPTIONS', tline)
+
+ def _cmake_target_include_directories(self, tline: CMakeTraceLine) -> None:
+ # DOC: https://cmake.org/cmake/help/latest/command/target_include_directories.html
+ self._parse_common_target_options('target_include_directories', 'INCLUDE_DIRECTORIES', 'INTERFACE_INCLUDE_DIRECTORIES', tline, ignore=['SYSTEM', 'BEFORE'], paths=True)
+
+ def _cmake_target_link_options(self, tline: CMakeTraceLine) -> None:
+ # DOC: https://cmake.org/cmake/help/latest/command/target_link_options.html
+ self._parse_common_target_options('target_link_options', 'LINK_OPTIONS', 'INTERFACE_LINK_OPTIONS', tline)
+
+ def _parse_common_target_options(self, func: str, private_prop: str, interface_prop: str, tline: CMakeTraceLine, ignore: Optional[List[str]] = None, paths: bool = False):
+ if ignore is None:
+ ignore = ['BEFORE']
+
+ args = list(tline.args)
+
+ if len(args) < 1:
+ return self._gen_exception(func, 'requires at least one argument', tline)
+
+ target = args[0]
+ if target not in self.targets:
+ return self._gen_exception(func, 'TARGET {} not found'.format(target), tline)
+
+ interface = []
+ private = []
+
+ mode = 'PUBLIC'
+ for i in args[1:]:
+ if i in ignore:
+ continue
+
+ if i in ['INTERFACE', 'PUBLIC', 'PRIVATE']:
+ mode = i
+ continue
+
+ if mode in ['INTERFACE', 'PUBLIC']:
+ interface += [i]
+
+ if mode in ['PUBLIC', 'PRIVATE']:
+ private += [i]
+
+ if paths:
+ interface = self._guess_files(interface)
+ private = self._guess_files(private)
+
+ interface = [x for x in interface if x]
+ private = [x for x in private if x]
+
+ for i in [(private_prop, private), (interface_prop, interface)]:
+ if not i[0] in self.targets[target].properies:
+ self.targets[target].properies[i[0]] = []
+
+ self.targets[target].properies[i[0]] += i[1]
+
def _lex_trace(self, trace):
# The trace format is: '<file>(<line>): <func>(<args -- can contain \n> )\n'
reg_tline = re.compile(r'\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(([\s\S]*?) ?\)\s*\n', re.MULTILINE)
reg_other = re.compile(r'[^\n]*\n')
- reg_genexp = re.compile(r'\$<.*>')
loc = 0
while loc < len(trace):
mo_file_line = reg_tline.match(trace, loc)
@@ -394,9 +466,10 @@ class CMakeTraceParser:
file = mo_file_line.group(1)
line = mo_file_line.group(3)
func = mo_file_line.group(4)
- args = mo_file_line.group(5).split(' ')
+ args = mo_file_line.group(5)
+ args = parse_generator_expressions(args)
+ args = args.split(' ')
args = list(map(lambda x: x.strip(), args))
- args = list(map(lambda x: reg_genexp.sub('', x), args)) # Remove generator expressions
yield CMakeTraceLine(file, line, func, args)
@@ -420,7 +493,7 @@ class CMakeTraceParser:
# Abort concatination if curr_str no longer matches the regex
fixed_list += [curr_str]
curr_str = i
- elif reg_end.match(i):
+ elif reg_end.match(i) or os.path.exists('{} {}'.format(curr_str, i)):
# File detected
curr_str = '{} {}'.format(curr_str, i)
fixed_list += [curr_str]
diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py
index 37e0ad1..6d9e814 100644
--- a/mesonbuild/compilers/__init__.py
+++ b/mesonbuild/compilers/__init__.py
@@ -33,7 +33,6 @@ __all__ = [
'is_object',
'is_source',
'lang_suffixes',
- 'sanitizer_compile_args',
'sort_clink',
'ArmCCompiler',
@@ -116,7 +115,6 @@ from .compilers import (
is_object,
is_library,
lang_suffixes,
- sanitizer_compile_args,
sort_clink,
CompilerArgs,
)
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 47cfd98..eff7161 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -67,6 +67,7 @@ class CCompiler(CLikeCompiler, Compiler):
#ifndef {symbol}
{symbol};
#endif
+ return 0;
}}'''
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 76c5c5e..3b61e61 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -12,9 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import abc, contextlib, enum, os.path, re, tempfile, shlex
-from typing import List, Optional, Tuple
-from pathlib import Path
+import contextlib, enum, os.path, re, tempfile, shlex
+from typing import Optional, Tuple, List
from ..linkers import StaticLinker
from .. import coredata
@@ -22,7 +21,7 @@ from .. import mlog
from .. import mesonlib
from ..mesonlib import (
EnvironmentException, MachineChoice, MesonException, OrderedSet,
- version_compare, Popen_safe
+ Popen_safe
)
from ..envconfig import (
Properties,
@@ -255,20 +254,6 @@ base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', T
'from_buildtype'),
}
-def sanitizer_compile_args(value):
- if value == 'none':
- return []
- args = ['-fsanitize=' + value]
- if 'address' in value: # For -fsanitize=address,undefined
- args.append('-fno-omit-frame-pointer')
- return args
-
-def sanitizer_link_args(value):
- if value == 'none':
- return []
- args = ['-fsanitize=' + value]
- return args
-
def option_enabled(boptions, options, option):
try:
if option not in boptions:
@@ -279,10 +264,9 @@ def option_enabled(boptions, options, option):
def get_base_compile_args(options, compiler):
args = []
- # FIXME, gcc/clang specific.
try:
if options['b_lto'].value:
- args.append('-flto')
+ args.extend(compiler.get_lto_compile_args())
except KeyError:
pass
try:
@@ -290,7 +274,7 @@ def get_base_compile_args(options, compiler):
except KeyError:
pass
try:
- args += sanitizer_compile_args(options['b_sanitize'].value)
+ args += compiler.sanitizer_compile_args(options['b_sanitize'].value)
except KeyError:
pass
try:
@@ -329,14 +313,13 @@ def get_base_compile_args(options, compiler):
def get_base_link_args(options, linker, is_shared_module):
args = []
- # FIXME, gcc/clang specific.
try:
if options['b_lto'].value:
- args.append('-flto')
+ args.extend(linker.get_lto_link_args())
except KeyError:
pass
try:
- args += sanitizer_link_args(options['b_sanitize'].value)
+ args += linker.sanitizer_link_args(options['b_sanitize'].value)
except KeyError:
pass
try:
@@ -363,7 +346,7 @@ def get_base_link_args(options, linker, is_shared_module):
args.append('-Wl,-bitcode_bundle')
elif as_needed:
# -Wl,-dead_strip_dylibs is incompatible with bitcode
- args.append(linker.get_asneeded_args())
+ args.extend(linker.get_asneeded_args())
try:
crt_val = options['b_vscrt'].value
buildtype = options['buildtype'].value
@@ -575,9 +558,9 @@ class CompilerArgs(list):
def append_direct(self, arg):
'''
- Append the specified argument without any reordering or de-dup
- except for absolute paths where the order of include search directories
- is not relevant
+ Append the specified argument without any reordering or de-dup except
+ for absolute paths to libraries, etc, which can always be de-duped
+ safely.
'''
if os.path.isabs(arg):
self.append(arg)
@@ -1198,6 +1181,18 @@ class Compiler:
def remove_linkerlike_args(self, args):
return [x for x in args if not x.startswith('-Wl')]
+ def get_lto_compile_args(self) -> List[str]:
+ return []
+
+ def get_lto_link_args(self) -> List[str]:
+ return []
+
+ def sanitizer_compile_args(self, value: str) -> List[str]:
+ return []
+
+ def sanitizer_link_args(self, value: str) -> List[str]:
+ return []
+
@enum.unique
class CompilerType(enum.Enum):
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 44f53eb..6ae2673 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -274,7 +274,6 @@ class PGICPPCompiler(PGICompiler, CPPCompiler):
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)
PGICompiler.__init__(self, compiler_type)
-
class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs):
GnuCPPCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, defines, **kwargs)
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index e417566..c10e2ca 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -321,6 +321,9 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler):
'2': default_warn_args,
'3': default_warn_args}
+ def language_stdlib_only_link_flags(self) -> List[str]:
+ return ['-lflang', '-lpgmath']
+
class Open64FortranCompiler(FortranCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags):
FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags)
diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py
index dfdf540..02654ce 100644
--- a/mesonbuild/compilers/mixins/arm.py
+++ b/mesonbuild/compilers/mixins/arm.py
@@ -161,8 +161,8 @@ class ArmclangCompiler:
def __init__(self, compiler_type: 'CompilerType'):
if not self.is_cross:
raise mesonlib.EnvironmentException('armclang supports only cross-compilation.')
- # Check whether 'armlink.exe' is available in path
- self.linker_exe = 'armlink.exe'
+ # Check whether 'armlink' is available in path
+ self.linker_exe = 'armlink'
args = '--vsn'
try:
p, stdo, stderr = mesonlib.Popen_safe(self.linker_exe, args)
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index e032402..37d2424 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -209,25 +209,25 @@ class CLikeCompiler:
'''
return self.get_compiler_dirs(env, 'programs')
- def get_pic_args(self):
+ def get_pic_args(self) -> typing.List[str]:
return ['-fPIC']
- def name_string(self):
+ def name_string(self) -> str:
return ' '.join(self.exelist)
- def get_pch_use_args(self, pch_dir, header):
+ def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]:
return ['-include', os.path.basename(header)]
- def get_pch_name(self, header_name):
+ def get_pch_name(self, header_name: str) -> str:
return os.path.basename(header_name) + '.' + self.get_pch_suffix()
- def get_linker_search_args(self, dirname):
+ def get_linker_search_args(self, dirname: str) -> typing.List[str]:
return ['-L' + dirname]
def get_default_include_dirs(self):
return []
- def gen_export_dynamic_link_args(self, env):
+ def gen_export_dynamic_link_args(self, env) -> typing.List[str]:
m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin():
return ['-Wl,--export-all-symbols']
@@ -236,7 +236,7 @@ class CLikeCompiler:
else:
return ['-Wl,-export-dynamic']
- def gen_import_library_args(self, implibname):
+ def gen_import_library_args(self, implibname: str) -> typing.List[str]:
"""
The name of the outputted import library
@@ -332,6 +332,7 @@ class CLikeCompiler:
#ifndef {symbol}
{symbol};
#endif
+ return 0;
}}'''
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
@@ -555,6 +556,7 @@ class CLikeCompiler:
{prefix}
int main() {{
{type} something;
+ return 0;
}}'''
if not self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)[0]:
@@ -633,6 +635,7 @@ class CLikeCompiler:
#include <stdio.h>
int main() {{
printf ("{fmt}", {cast} {f}());
+ return 0;
}}'''.format(**fargs)
res = self.run(code, env, extra_args=extra_args, dependencies=dependencies)
if not res.compiled:
@@ -785,6 +788,7 @@ class CLikeCompiler:
#error "No definition for __builtin_{func} found in the prefix"
#endif
#endif
+ return 0;
}}'''
return self.links(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index 46f04c4..9756604 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -188,15 +188,15 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
# All GCC-like backends can do assembly
self.can_compile_suffixes.add('s')
- def get_asneeded_args(self) -> str:
+ def get_asneeded_args(self) -> typing.List[str]:
# GNU ld cannot be installed on macOS
# https://github.com/Homebrew/homebrew-core/issues/17794#issuecomment-328174395
# Hence, we don't need to differentiate between OS and ld
# for the sake of adding as-needed support
if self.compiler_type.is_osx_compiler:
- return '-Wl,-dead_strip_dylibs'
+ return ['-Wl,-dead_strip_dylibs']
else:
- return '-Wl,--as-needed'
+ return ['-Wl,--as-needed']
def get_pic_args(self) -> typing.List[str]:
if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler:
@@ -366,6 +366,25 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
return self._split_fetch_real_dirs(line.split('=', 1)[1])
return []
+ def get_lto_compile_args(self) -> typing.List[str]:
+ return ['-flto']
+
+ def get_lto_link_args(self) -> typing.List[str]:
+ return ['-flto']
+
+ def sanitizer_compile_args(self, value: str) -> typing.List[str]:
+ if value == 'none':
+ return []
+ args = ['-fsanitize=' + value]
+ if 'address' in value: # for -fsanitize=address,undefined
+ args.append('-fno-omit-frame-pointer')
+ return args
+
+ def sanitizer_link_args(self, value: str) -> typing.List[str]:
+ if value == 'none':
+ return []
+ return ['-fsanitize=' + value]
+
class GnuCompiler(GnuLikeCompiler):
"""
diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py
index f147c4c..7fadb50 100644
--- a/mesonbuild/compilers/mixins/intel.py
+++ b/mesonbuild/compilers/mixins/intel.py
@@ -22,14 +22,13 @@ import os
import typing
from ... import mesonlib
+from ..compilers import CompilerType
from .gnu import GnuLikeCompiler
from .visualstudio import VisualStudioLikeCompiler
if typing.TYPE_CHECKING:
import subprocess # noqa: F401
- from ..compilers import CompilerType
-
# XXX: avoid circular dependencies
# TODO: this belongs in a posix compiler class
clike_optimization_args = {
diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py
index a75c62d..0613e79 100644
--- a/mesonbuild/compilers/mixins/pgi.py
+++ b/mesonbuild/compilers/mixins/pgi.py
@@ -16,6 +16,7 @@
import typing
import os
+from pathlib import Path
from ..compilers import clike_debug_args, clike_optimization_args
@@ -42,8 +43,9 @@ pgi_buildtype_linker_args = {
} # type: typing.Dict[str, typing.List[str]]
-class PGICompiler:
+class PGICompiler():
def __init__(self, compiler_type: 'CompilerType'):
+ self.base_options = ['b_pch']
self.id = 'pgi'
self.compiler_type = compiler_type
@@ -59,9 +61,21 @@ class PGICompiler:
def get_no_warn_args(self) -> typing.List[str]:
return ['-silent']
+ def gen_import_library_args(self, implibname: str) -> typing.List[str]:
+ return []
+
+ def get_std_shared_lib_link_args(self) -> typing.List[str]:
+ # PGI -shared is Linux only.
+ if self.compiler_type.is_windows_compiler:
+ return ['-Bdynamic', '-Mmakedll']
+ elif not self.compiler_type.is_osx_compiler:
+ return ['-shared']
+ return []
+
def get_pic_args(self) -> typing.List[str]:
+ # PGI -fPIC is Linux only.
if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler:
- return [] # PGI -fPIC is Linux only.
+ return []
return ['-fPIC']
def openmp_flags(self) -> typing.List[str]:
@@ -93,3 +107,17 @@ class PGICompiler:
def get_always_args(self) -> typing.List[str]:
return []
+
+ def get_pch_suffix(self) -> str:
+ # PGI defaults to .pch suffix for PCH on Linux and Windows with --pch option
+ return 'pch'
+
+ def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]:
+ # PGI supports PCH for C++ only.
+ hdr = Path(pch_dir).resolve().parent / header
+ if self.language == 'cpp':
+ return ['--pch',
+ '--pch_dir', str(hdr.parent),
+ '-I{}'.format(hdr.parent)]
+ else:
+ return []
diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py
index 0a612ae..d8734fc 100644
--- a/mesonbuild/compilers/vala.py
+++ b/mesonbuild/compilers/vala.py
@@ -38,7 +38,7 @@ class ValaCompiler(Compiler):
return []
def get_debug_args(self, is_debug):
- return ['--debug']
+ return ['--debug'] if is_debug else []
def get_output_args(self, target):
return [] # Because compiles into C.
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 1a397c7..048a29c 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -35,6 +35,8 @@ import enum
if typing.TYPE_CHECKING:
from . import dependencies
+ OptionDictType = typing.Dict[str, 'UserOption[Any]']
+
version = '0.51.999'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'vs2019', 'xcode']
@@ -387,14 +389,17 @@ class CoreData:
if not filenames:
return []
- real = []
+ found_invalid = [] # type: typing.List[str]
+ missing = [] # type: typing.List[str]
+ real = [] # type: typing.List[str]
for i, f in enumerate(filenames):
f = os.path.expanduser(os.path.expandvars(f))
if os.path.exists(f):
if os.path.isfile(f):
real.append(os.path.abspath(f))
+ continue
elif os.path.isdir(f):
- raise MesonException('Cross and native files must not be directories')
+ found_invalid.append(os.path.abspath(f))
else:
# in this case we've been passed some kind of pipe, copy
# the contents of that file into the meson private (scratch)
@@ -408,8 +413,8 @@ class CoreData:
# Also replace the command line argument, as the pipe
# probably wont exist on reconfigure
filenames[i] = copy
- continue
- elif sys.platform != 'win32':
+ continue
+ if sys.platform != 'win32':
paths = [
os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')),
] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':')
@@ -419,9 +424,14 @@ class CoreData:
real.append(path_to_try)
break
else:
- raise MesonException('Cannot find specified {} file: {}'.format(ftype, f))
- continue
+ missing.append(f)
+ else:
+ missing.append(f)
+ if missing:
+ if found_invalid:
+ mlog.log('Found invalid candidates for', ftype, 'file:', *found_invalid)
+ mlog.log('Could not find any valid candidate for', ftype, 'files:', *missing)
raise MesonException('Cannot find specified {} file: {}'.format(ftype, f))
return real
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 8616367..22f4c6f 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -1035,6 +1035,12 @@ class CMakeDependency(ExternalDependency):
cm_args.append('-DCMAKE_MODULE_PATH=' + ';'.join(cm_path))
pref_path = self.env.coredata.builtins_per_machine[self.for_machine]['cmake_prefix_path'].value
+ if 'CMAKE_PREFIX_PATH' in os.environ:
+ env_pref_path = os.environ['CMAKE_PREFIX_PATH'].split(':')
+ env_pref_path = [x for x in env_pref_path if x] # Filter out enpty strings
+ if not pref_path:
+ pref_path = []
+ pref_path += env_pref_path
if pref_path:
cm_args.append('-DCMAKE_PREFIX_PATH={}'.format(';'.join(pref_path)))
@@ -1290,15 +1296,18 @@ class CMakeDependency(ExternalDependency):
# Failed to guess a target --> try the old-style method
if len(modules) == 0:
- incDirs = self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS')
- defs = self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS')
- libs = self.traceparser.get_cmake_var('PACKAGE_LIBRARIES')
+ incDirs = [x for x in self.traceparser.get_cmake_var('PACKAGE_INCLUDE_DIRS') if x]
+ defs = [x for x in self.traceparser.get_cmake_var('PACKAGE_DEFINITIONS') if x]
+ libs = [x for x in self.traceparser.get_cmake_var('PACKAGE_LIBRARIES') if x]
# Try to use old style variables if no module is specified
if len(libs) > 0:
self.compile_args = list(map(lambda x: '-I{}'.format(x), incDirs)) + defs
self.link_args = libs
mlog.debug('using old-style CMake variables for dependency {}'.format(name))
+ mlog.debug('Include Dirs: {}'.format(incDirs))
+ mlog.debug('Compiler Definitions: {}'.format(defs))
+ mlog.debug('Libraries: {}'.format(libs))
return
# Even the old-style approach failed. Nothing else we can do here
@@ -1340,39 +1349,37 @@ class CMakeDependency(ExternalDependency):
mlog.debug(tgt)
if 'INTERFACE_INCLUDE_DIRECTORIES' in tgt.properies:
- incDirs += tgt.properies['INTERFACE_INCLUDE_DIRECTORIES']
+ incDirs += [x for x in tgt.properies['INTERFACE_INCLUDE_DIRECTORIES'] if x]
if 'INTERFACE_COMPILE_DEFINITIONS' in tgt.properies:
- tempDefs = list(tgt.properies['INTERFACE_COMPILE_DEFINITIONS'])
- tempDefs = list(map(lambda x: '-D{}'.format(re.sub('^-D', '', x)), tempDefs))
- compileDefinitions += tempDefs
+ compileDefinitions += ['-D' + re.sub('^-D', '', x) for x in tgt.properies['INTERFACE_COMPILE_DEFINITIONS'] if x]
if 'INTERFACE_COMPILE_OPTIONS' in tgt.properies:
- compileOptions += tgt.properies['INTERFACE_COMPILE_OPTIONS']
+ compileOptions += [x for x in tgt.properies['INTERFACE_COMPILE_OPTIONS'] if x]
if 'IMPORTED_CONFIGURATIONS' in tgt.properies:
- cfgs = tgt.properies['IMPORTED_CONFIGURATIONS']
+ cfgs = [x for x in tgt.properies['IMPORTED_CONFIGURATIONS'] if x]
cfg = cfgs[0]
if 'RELEASE' in cfgs:
cfg = 'RELEASE'
if 'IMPORTED_IMPLIB_{}'.format(cfg) in tgt.properies:
- libraries += tgt.properies['IMPORTED_IMPLIB_{}'.format(cfg)]
+ libraries += [x for x in tgt.properies['IMPORTED_IMPLIB_{}'.format(cfg)] if x]
elif 'IMPORTED_IMPLIB' in tgt.properies:
- libraries += tgt.properies['IMPORTED_IMPLIB']
+ libraries += [x for x in tgt.properies['IMPORTED_IMPLIB'] if x]
elif 'IMPORTED_LOCATION_{}'.format(cfg) in tgt.properies:
- libraries += tgt.properies['IMPORTED_LOCATION_{}'.format(cfg)]
+ libraries += [x for x in tgt.properies['IMPORTED_LOCATION_{}'.format(cfg)] if x]
elif 'IMPORTED_LOCATION' in tgt.properies:
- libraries += tgt.properies['IMPORTED_LOCATION']
+ libraries += [x for x in tgt.properies['IMPORTED_LOCATION'] if x]
if 'INTERFACE_LINK_LIBRARIES' in tgt.properies:
- otherDeps += tgt.properies['INTERFACE_LINK_LIBRARIES']
+ otherDeps += [x for x in tgt.properies['INTERFACE_LINK_LIBRARIES'] if x]
if 'IMPORTED_LINK_DEPENDENT_LIBRARIES_{}'.format(cfg) in tgt.properies:
- otherDeps += tgt.properies['IMPORTED_LINK_DEPENDENT_LIBRARIES_{}'.format(cfg)]
+ otherDeps += [x for x in tgt.properies['IMPORTED_LINK_DEPENDENT_LIBRARIES_{}'.format(cfg)] if x]
elif 'IMPORTED_LINK_DEPENDENT_LIBRARIES' in tgt.properies:
- otherDeps += tgt.properies['IMPORTED_LINK_DEPENDENT_LIBRARIES']
+ otherDeps += [x for x in tgt.properies['IMPORTED_LINK_DEPENDENT_LIBRARIES'] if x]
for j in otherDeps:
if j in self.traceparser.targets:
@@ -1391,23 +1398,19 @@ class CMakeDependency(ExternalDependency):
mlog.debug('Compiler Options: {}'.format(compileOptions))
mlog.debug('Libraries: {}'.format(libraries))
- self.compile_args = compileOptions + compileDefinitions + list(map(lambda x: '-I{}'.format(x), incDirs))
+ self.compile_args = compileOptions + compileDefinitions + ['-I{}'.format(x) for x in incDirs]
self.link_args = libraries
def _setup_cmake_dir(self, cmake_file: str) -> str:
# Setup the CMake build environment and return the "build" directory
- build_dir = '{}/cmake_{}'.format(self.cmake_root_dir, self.name)
- os.makedirs(build_dir, exist_ok=True)
+ build_dir = Path(self.cmake_root_dir) / 'cmake_{}'.format(self.name)
+ build_dir.mkdir(parents=True, exist_ok=True)
# Copy the CMakeLists.txt
- cmake_lists = '{}/CMakeLists.txt'.format(build_dir)
- dir_path = os.path.dirname(os.path.realpath(__file__))
- src_cmake = '{}/data/{}'.format(dir_path, cmake_file)
- if os.path.exists(cmake_lists):
- os.remove(cmake_lists)
- shutil.copyfile(src_cmake, cmake_lists)
+ src_cmake = Path(__file__).parent / 'data' / cmake_file
+ shutil.copyfile(str(src_cmake), str(build_dir / 'CMakeLists.txt')) # str() is for Python 3.5
- return build_dir
+ return str(build_dir)
def _call_cmake(self, args, cmake_file: str, env=None):
build_dir = self._setup_cmake_dir(cmake_file)
@@ -1542,7 +1545,7 @@ class DubDependency(ExternalDependency):
for lib in target['buildSettings'][field_name]:
if lib not in libs:
libs.append(lib)
- if os.name is not 'nt':
+ if os.name != 'nt':
pkgdep = PkgConfigDependency(lib, environment, {'required': 'true', 'silent': 'true'})
for arg in pkgdep.get_compile_args():
self.compile_args.append(arg)
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 1bb1b6e..53c3747 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -370,20 +370,30 @@ class OpenMPDependency(ExternalDependency):
language = kwargs.get('language')
super().__init__('openmp', environment, language, kwargs)
self.is_found = False
+ if self.clib_compiler.get_id() == 'pgi':
+ # through at least PGI 19.4, there is no macro defined for OpenMP, but OpenMP 3.1 is supported.
+ self.version = '3.1'
+ self.is_found = True
+ self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+ return
try:
openmp_date = self.clib_compiler.get_define(
'_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self], disable_cache=True)[0]
except mesonlib.EnvironmentException as e:
mlog.debug('OpenMP support not available in the compiler')
mlog.debug(e)
- openmp_date = False
+ openmp_date = None
if openmp_date:
self.version = self.VERSIONS[openmp_date]
- if self.clib_compiler.has_header('omp.h', '', self.env, dependencies=[self], disable_cache=True)[0]:
- self.is_found = True
- self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
- else:
+ # Flang has omp_lib.h
+ header_names = ('omp.h', 'omp_lib.h')
+ for name in header_names:
+ if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]:
+ self.is_found = True
+ self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+ break
+ if not self.is_found:
mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index a47208d..6c30fc1 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -763,7 +763,6 @@ class Environment:
target = 'x86' if 'IA-32' in err else 'x86_64'
cls = IntelClCCompiler if lang == 'c' else IntelClCPPCompiler
return cls(compiler, version, for_machine, is_cross, exe_wrap, target)
- return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version)
if 'Microsoft' in out or 'Microsoft' in err:
# Latest versions of Visual Studio print version
# number to stderr but earlier ones print version
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index fd94251..0891094 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -21,7 +21,7 @@ from . import optinterpreter
from . import compilers
from .wrap import wrap, WrapMode
from . import mesonlib
-from .mesonlib import FileMode, MachineChoice, PerMachine, Popen_safe, listify, extract_as_list, has_path_sep
+from .mesonlib import FileMode, MachineChoice, Popen_safe, listify, extract_as_list, has_path_sep
from .dependencies import ExternalProgram
from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
from .interpreterbase import InterpreterBase
@@ -40,7 +40,7 @@ from collections import namedtuple
from itertools import chain
from pathlib import PurePath
import functools
-from typing import Sequence, List, Union, Optional, Iterator, Dict, Any
+from typing import Sequence, List, Union, Optional, Dict, Any
import importlib
@@ -444,7 +444,7 @@ class DependencyHolder(InterpreterObject, ObjectHolder):
@FeatureNew('dep.get_variable', '0.51.0')
@noPosargs
- @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default', 'pkgconfig_define'})
+ @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default_value', 'pkgconfig_define'})
def variable_method(self, args, kwargs):
return self.held_object.get_variable(**kwargs)
@@ -489,6 +489,7 @@ class ExternalProgramHolder(InterpreterObject, ObjectHolder):
ObjectHolder.__init__(self, ep)
self.methods.update({'found': self.found_method,
'path': self.path_method})
+ self.cached_version = None
@noPosargs
@permittedKwargs({})
@@ -509,6 +510,24 @@ class ExternalProgramHolder(InterpreterObject, ObjectHolder):
def get_name(self):
return self.held_object.get_name()
+ def get_version(self, interpreter):
+ if not self.cached_version:
+ raw_cmd = self.get_command() + ['--version']
+ cmd = [self, '--version']
+ res = interpreter.run_command_impl(interpreter.current_node, cmd, {}, True)
+ if res.returncode != 0:
+ m = 'Running {!r} failed'
+ raise InterpreterException(m.format(raw_cmd))
+ output = res.stdout.strip()
+ if not output:
+ output = res.stderr.strip()
+ match = re.search(r'([0-9\.]+)', output)
+ if not match:
+ m = 'Could not find a version number in output of {!r}'
+ raise InterpreterException(m.format(raw_cmd))
+ self.cached_version = match.group(1)
+ return self.cached_version
+
class ExternalLibraryHolder(InterpreterObject, ObjectHolder):
def __init__(self, el, pv):
InterpreterObject.__init__(self)
@@ -1993,7 +2012,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'},
'version',
},
'executable': build.known_exe_kwargs,
- 'find_program': {'required', 'native'},
+ 'find_program': {'required', 'native', 'version'},
'generator': {'arguments',
'output',
'depends',
@@ -2879,7 +2898,7 @@ external dependencies (including libraries) must go to "dependencies".''')
# TODO update modules to always pass `for_machine`. It is bad-form to assume
# the host machine.
- def find_program_impl(self, args, for_machine: MachineChoice = MachineChoice.HOST, required=True, silent=True):
+ def find_program_impl(self, args, for_machine: MachineChoice = MachineChoice.HOST, required=True, silent=True, wanted=''):
if not isinstance(args, list):
args = [args]
@@ -2897,8 +2916,20 @@ external dependencies (including libraries) must go to "dependencies".''')
return ExternalProgramHolder(dependencies.NonExistingExternalProgram())
# Only store successful lookups
self.store_name_lookups(args)
+ if wanted:
+ version = progobj.get_version(self)
+ is_found, not_found, found = mesonlib.version_compare_many(version, wanted)
+ if not is_found:
+ mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'),
+ 'found {!r} but need:'.format(version),
+ ', '.join(["'{}'".format(e) for e in not_found]))
+ if required:
+ m = 'Invalid version of program, need {!r} {!r} found {!r}.'
+ raise InvalidArguments(m.format(progobj.get_name(), not_found, version))
+ return ExternalProgramHolder(dependencies.NonExistingExternalProgram())
return progobj
+ @FeatureNewKwargs('find_program', '0.52.0', ['version'])
@FeatureNewKwargs('find_program', '0.49.0', ['disabler'])
@disablerIfNotFound
@permittedKwargs(permitted_kwargs['find_program'])
@@ -2913,8 +2944,9 @@ external dependencies (including libraries) must go to "dependencies".''')
if not isinstance(required, bool):
raise InvalidArguments('"required" argument must be a boolean.')
+ wanted = mesonlib.stringlistify(kwargs.get('version', []))
for_machine = self.machine_from_native_kwarg(kwargs)
- return self.find_program_impl(args, for_machine, required=required, silent=False)
+ return self.find_program_impl(args, for_machine, required=required, silent=False, wanted=wanted)
def func_find_library(self, node, args, kwargs):
raise InvalidCode('find_library() is removed, use meson.get_compiler(\'name\').find_library() instead.\n'
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 71a4ef3..b5510cf 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -337,20 +337,25 @@ class Disabler(InterpreterObject):
def found_method(self, args, kwargs):
return False
-def is_disabler(i):
+def is_disabler(i) -> bool:
return isinstance(i, Disabler)
-def is_disabled(args, kwargs):
+def is_arg_disabled(arg) -> bool:
+ if is_disabler(arg):
+ return True
+ if isinstance(arg, list):
+ for i in arg:
+ if is_arg_disabled(i):
+ return True
+ return False
+
+def is_disabled(args, kwargs) -> bool:
for i in args:
- if isinstance(i, Disabler):
+ if is_arg_disabled(i):
return True
for i in kwargs.values():
- if isinstance(i, Disabler):
+ if is_arg_disabled(i):
return True
- if isinstance(i, list):
- for j in i:
- if isinstance(j, Disabler):
- return True
return False
class InterpreterBase:
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index 648d1ef..dc9a825 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -12,173 +12,161 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from .mesonlib import Popen_safe, is_windows
+import typing
+
from . import mesonlib
+if typing.TYPE_CHECKING:
+ from .coredata import OptionDictType
+ from .environment import Environment
+
+
class StaticLinker:
- def can_linker_accept_rsp(self):
+
+ def __init__(self, exelist: typing.List[str]):
+ self.exelist = exelist
+
+ def can_linker_accept_rsp(self) -> bool:
"""
Determines whether the linker can accept arguments using the @rsp syntax.
"""
return mesonlib.is_windows()
+ def get_base_link_args(self, options: 'OptionDictType') -> typing.List[str]:
+ """Like compilers.get_base_link_args, but for the static linker."""
+ return []
-class VisualStudioLikeLinker:
- always_args = ['/NOLOGO']
-
- def __init__(self, exelist, machine):
- self.exelist = exelist
- self.machine = machine
-
- def get_exelist(self):
+ def get_exelist(self) -> typing.List[str]:
return self.exelist.copy()
- def get_std_link_args(self):
+ def get_std_link_args(self) -> typing.List[str]:
return []
- def get_buildtype_linker_args(self, buildtype):
+ def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]:
return []
- def get_output_args(self, target):
- args = []
- if self.machine:
- args += ['/MACHINE:' + self.machine]
- args += ['/OUT:' + target]
- return args
+ def get_output_args(self, target: str) -> typing.List[str]:
+ return[]
- def get_coverage_link_args(self):
+ def get_coverage_link_args(self) -> typing.List[str]:
return []
- def get_always_args(self):
- return self.always_args.copy()
+ def build_rpath_args(self, build_dir: str, from_dir: str, rpath_paths: str,
+ build_rpath: str, install_rpath: str) -> typing.List[str]:
+ return []
- def get_linker_always_args(self):
- return self.always_args.copy()
+ def thread_link_flags(self, env: 'Environment') -> typing.List[str]:
+ return []
+
+ def openmp_flags(self) -> typing.List[str]:
+ return []
- def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
+ def get_option_link_args(self, options: 'OptionDictType') -> typing.List[str]:
return []
- def thread_link_flags(self, env):
+ @classmethod
+ def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]:
+ return args
+
+ def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]:
+ # Static libraries do not have PDB files
return []
- def openmp_flags(self):
+ def get_always_args(self) -> typing.List[str]:
return []
- def get_option_link_args(self, options):
+ def get_linker_always_args(self) -> typing.List[str]:
return []
+
+class VisualStudioLikeLinker:
+ always_args = ['/NOLOGO']
+
+ def __init__(self, machine: str):
+ self.machine = machine
+
+ def get_always_args(self) -> typing.List[str]:
+ return self.always_args.copy()
+
+ def get_linker_always_args(self) -> typing.List[str]:
+ return self.always_args.copy()
+
+ def get_output_args(self, target: str) -> typing.List[str]:
+ args = [] # type: typing.List[str]
+ if self.machine:
+ args += ['/MACHINE:' + self.machine]
+ args += ['/OUT:' + target]
+ return args
+
@classmethod
- def unix_args_to_native(cls, args):
+ def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]:
from .compilers import VisualStudioCCompiler
return VisualStudioCCompiler.unix_args_to_native(args)
- def get_link_debugfile_args(self, targetfile):
- # Static libraries do not have PDB files
- return []
-
class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
"""Microsoft's lib static linker."""
+ def __init__(self, exelist: typing.List[str], machine: str):
+ StaticLinker.__init__(self, exelist)
+ VisualStudioLikeLinker.__init__(self, machine)
+
class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker):
"""Intel's xilib static linker."""
+ def __init__(self, exelist: typing.List[str], machine: str):
+ StaticLinker.__init__(self, exelist)
+ VisualStudioLikeLinker.__init__(self, machine)
+
class ArLinker(StaticLinker):
- def __init__(self, exelist):
- self.exelist = exelist
+ def __init__(self, exelist: typing.List[str]):
+ super().__init__(exelist)
self.id = 'ar'
- pc, stdo = Popen_safe(self.exelist + ['-h'])[0:2]
+ pc, stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[0:2]
# Enable deterministic builds if they are available.
if '[D]' in stdo:
self.std_args = ['csrD']
else:
self.std_args = ['csr']
- def can_linker_accept_rsp(self):
- return mesonlib.is_windows()
-
- def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
- return []
-
- def get_exelist(self):
- return self.exelist[:]
-
- def get_std_link_args(self):
+ def get_std_link_args(self) -> typing.List[str]:
return self.std_args
- def get_output_args(self, target):
+ def get_output_args(self, target: str) -> typing.List[str]:
return [target]
- def get_buildtype_linker_args(self, buildtype):
- return []
-
- def get_linker_always_args(self):
- return []
-
- def get_coverage_link_args(self):
- return []
-
- def get_always_args(self):
- return []
-
- def thread_link_flags(self, env):
- return []
-
- def openmp_flags(self):
- return []
-
- def get_option_link_args(self, options):
- return []
-
- @classmethod
- def unix_args_to_native(cls, args):
- return args[:]
-
- def get_link_debugfile_args(self, targetfile):
- return []
class ArmarLinker(ArLinker):
- def __init__(self, exelist):
- self.exelist = exelist
+ def __init__(self, exelist: typing.List[str]):
+ StaticLinker.__init__(self, exelist)
self.id = 'armar'
self.std_args = ['-csr']
- def can_linker_accept_rsp(self):
+ def can_linker_accept_rsp(self) -> bool:
# armar cann't accept arguments using the @rsp syntax
return False
+
class DLinker(StaticLinker):
- def __init__(self, exelist, arch):
- self.exelist = exelist
+ def __init__(self, exelist: typing.List[str], arch: str):
+ super().__init__(exelist)
self.id = exelist[0]
self.arch = arch
- def can_linker_accept_rsp(self):
- return mesonlib.is_windows()
-
- def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
- return []
-
- def get_exelist(self):
- return self.exelist[:]
-
- def get_std_link_args(self):
+ def get_std_link_args(self) -> typing.List[str]:
return ['-lib']
- def get_output_args(self, target):
+ def get_output_args(self, target: str) -> typing.List[str]:
return ['-of=' + target]
- def get_buildtype_linker_args(self, buildtype):
- return []
-
- def get_linker_always_args(self):
- if is_windows():
+ def get_linker_always_args(self) -> typing.List[str]:
+ if mesonlib.is_windows():
if self.arch == 'x86_64':
return ['-m64']
elif self.arch == 'x86_mscoff' and self.id == 'dmd':
@@ -186,75 +174,18 @@ class DLinker(StaticLinker):
return ['-m32']
return []
- def get_coverage_link_args(self):
- return []
-
- def get_always_args(self):
- return []
-
- def thread_link_flags(self, env):
- return []
-
- def openmp_flags(self):
- return []
-
- def get_option_link_args(self, options):
- return []
-
- @classmethod
- def unix_args_to_native(cls, args):
- return args[:]
-
- def get_link_debugfile_args(self, targetfile):
- return []
class CcrxLinker(StaticLinker):
- def __init__(self, exelist):
- self.exelist = exelist
+ def __init__(self, exelist: typing.List[str]):
+ super().__init__(exelist)
self.id = 'rlink'
- pc, stdo = Popen_safe(self.exelist + ['-h'])[0:2]
- self.std_args = []
- def can_linker_accept_rsp(self):
+ def can_linker_accept_rsp(self) -> bool:
return False
- def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
- return []
-
- def get_exelist(self):
- return self.exelist[:]
-
- def get_std_link_args(self):
- return self.std_args
-
- def get_output_args(self, target):
+ def get_output_args(self, target: str) -> typing.List[str]:
return ['-output=%s' % target]
- def get_buildtype_linker_args(self, buildtype):
- return []
-
- def get_linker_always_args(self):
+ def get_linker_always_args(self) -> typing.List[str]:
return ['-nologo', '-form=library']
-
- def get_coverage_link_args(self):
- return []
-
- def get_always_args(self):
- return []
-
- def thread_link_flags(self, env):
- return []
-
- def openmp_flags(self):
- return []
-
- def get_option_link_args(self, options):
- return []
-
- @classmethod
- def unix_args_to_native(cls, args):
- return args[:]
-
- def get_link_debugfile_args(self, targetfile):
- return []
diff --git a/mesonbuild/scripts/dist.py b/mesonbuild/mdist.py
index 1a62c70..2d1aaf9 100644
--- a/mesonbuild/scripts/dist.py
+++ b/mesonbuild/mdist.py
@@ -14,18 +14,27 @@
import lzma
+import gzip
import os
import sys
import shutil
import subprocess
-import pickle
import hashlib
-import tarfile, zipfile
-import tempfile
+import json
from glob import glob
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import windows_proof_rmtree
-from mesonbuild import mlog
+from mesonbuild import mlog, build
+
+archive_choices = ['gztar', 'xztar', 'zip']
+archive_extension = {'gztar': '.tar.gz',
+ 'xztar': '.tar.xz',
+ 'zip': '.zip'}
+
+def add_arguments(parser):
+ parser.add_argument('--formats', default='xztar',
+ help='Comma separated list of archive types to create.')
+
def create_hash(fname):
hashname = fname + '.sha256sum'
@@ -35,22 +44,6 @@ def create_hash(fname):
f.write('%s %s\n' % (m.hexdigest(), os.path.basename(fname)))
-def create_zip(zipfilename, packaging_dir):
- prefix = os.path.dirname(packaging_dir)
- removelen = len(prefix) + 1
- with zipfile.ZipFile(zipfilename,
- 'w',
- compression=zipfile.ZIP_DEFLATED,
- allowZip64=True) as zf:
- zf.write(packaging_dir, packaging_dir[removelen:])
- for root, dirs, files in os.walk(packaging_dir):
- for d in dirs:
- dname = os.path.join(root, d)
- zf.write(dname, dname[removelen:])
- for f in files:
- fname = os.path.join(root, f)
- zf.write(fname, fname[removelen:])
-
def del_gitfiles(dirname):
for f in glob(os.path.join(dirname, '.git*')):
if os.path.isdir(f) and not os.path.islink(f):
@@ -98,7 +91,7 @@ def git_have_dirty_index(src_root):
ret = subprocess.call(['git', '-C', src_root, 'diff-index', '--quiet', 'HEAD'])
return ret == 1
-def create_dist_git(dist_name, src_root, bld_root, dist_sub, dist_scripts):
+def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts):
if git_have_dirty_index(src_root):
mlog.warning('Repository has uncommitted changes that will not be included in the dist tarball')
distdir = os.path.join(dist_sub, dist_name)
@@ -109,15 +102,13 @@ def create_dist_git(dist_name, src_root, bld_root, dist_sub, dist_scripts):
process_submodules(distdir)
del_gitfiles(distdir)
run_dist_scripts(distdir, dist_scripts)
- xzname = distdir + '.tar.xz'
- # Should use shutil but it got xz support only in 3.5.
- with tarfile.open(xzname, 'w:xz') as tf:
- tf.add(distdir, dist_name)
- # Create only .tar.xz for now.
- # zipname = distdir + '.zip'
- # create_zip(zipname, distdir)
+ output_names = []
+ for a in archives:
+ compressed_name = distdir + archive_extension[a]
+ shutil.make_archive(distdir, a, root_dir=dist_sub, base_dir=dist_name)
+ output_names.append(compressed_name)
shutil.rmtree(distdir)
- return (xzname, )
+ return output_names
def hg_have_dirty_index(src_root):
@@ -125,26 +116,35 @@ def hg_have_dirty_index(src_root):
out = subprocess.check_output(['hg', '-R', src_root, 'summary'])
return b'commit: (clean)' not in out
-def create_dist_hg(dist_name, src_root, bld_root, dist_sub, dist_scripts):
+def create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, dist_scripts):
if hg_have_dirty_index(src_root):
mlog.warning('Repository has uncommitted changes that will not be included in the dist tarball')
os.makedirs(dist_sub, exist_ok=True)
tarname = os.path.join(dist_sub, dist_name + '.tar')
xzname = tarname + '.xz'
+ gzname = tarname + '.gz'
+ zipname = os.path.join(dist_sub, dist_name + '.zip')
subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'tar', tarname])
+ output_names = []
if dist_scripts:
mlog.warning('dist scripts are not supported in Mercurial projects')
- with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf:
- shutil.copyfileobj(tf, xf)
+ if 'xztar' in archives:
+ with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf:
+ shutil.copyfileobj(tf, xf)
+ output_names.append(xzname)
+ if 'gztar' in archives:
+ with gzip.open(gzname, 'wb') as zf, open(tarname, 'rb') as tf:
+ shutil.copyfileobj(tf, zf)
+ output_names.append(gzname)
os.unlink(tarname)
- # Create only .tar.xz for now.
- # zipname = os.path.join(dist_sub, dist_name + '.zip')
- # subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'zip', zipname])
- return (xzname, )
+ if 'zip' in archives:
+ subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'zip', zipname])
+ output_names.append(zipname)
+ return output_names
-def check_dist(packagename, meson_command, privdir):
+def check_dist(packagename, meson_command, bld_root, privdir):
print('Testing distribution package %s' % packagename)
unpackdir = os.path.join(privdir, 'dist-unpack')
builddir = os.path.join(privdir, 'dist-build')
@@ -155,10 +155,14 @@ def check_dist(packagename, meson_command, privdir):
os.mkdir(p)
ninja_bin = detect_ninja()
try:
- tf = tarfile.open(packagename)
- tf.extractall(unpackdir)
- srcdir = glob(os.path.join(unpackdir, '*'))[0]
- if subprocess.call(meson_command + ['--backend=ninja', srcdir, builddir]) != 0:
+ shutil.unpack_archive(packagename, unpackdir)
+ unpacked_files = glob(os.path.join(unpackdir, '*'))
+ assert(len(unpacked_files) == 1)
+ unpacked_src_dir = unpacked_files[0]
+ with open(os.path.join(bld_root, 'meson-info', 'intro-buildoptions.json')) as boptions:
+ meson_command += ['-D{name}={value}'.format(**o) for o in json.load(boptions)
+ if o['name'] not in ['backend', 'install_umask']]
+ if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0:
print('Running Meson on distribution package failed')
return 1
if subprocess.call([ninja_bin], cwd=builddir) != 0:
@@ -179,33 +183,43 @@ def check_dist(packagename, meson_command, privdir):
print('Distribution package %s tested' % packagename)
return 0
-def run(args):
- src_root = args[0]
- bld_root = args[1]
- meson_command = args[2:]
+def determine_archives_to_generate(options):
+ result = []
+ for i in options.formats.split(','):
+ if i not in archive_choices:
+ sys.exit('Value "{}" not one of permitted values {}.'.format(i, archive_choices))
+ result.append(i)
+ if len(i) == 0:
+ sys.exit('No archive types specified.')
+ return result
+
+def run(options):
+ b = build.load('.')
+ # This import must be load delayed, otherwise it will get the default
+ # value of None.
+ from mesonbuild.mesonlib import meson_command
+ src_root = b.environment.source_dir
+ bld_root = b.environment.build_dir
priv_dir = os.path.join(bld_root, 'meson-private')
dist_sub = os.path.join(bld_root, 'meson-dist')
- buildfile = os.path.join(priv_dir, 'build.dat')
-
- build = pickle.load(open(buildfile, 'rb'))
+ dist_name = b.project_name + '-' + b.project_version
- dist_name = build.project_name + '-' + build.project_version
+ archives = determine_archives_to_generate(options)
_git = os.path.join(src_root, '.git')
if os.path.isdir(_git) or os.path.isfile(_git):
- names = create_dist_git(dist_name, src_root, bld_root, dist_sub, build.dist_scripts)
+ names = create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, b.dist_scripts)
elif os.path.isdir(os.path.join(src_root, '.hg')):
- names = create_dist_hg(dist_name, src_root, bld_root, dist_sub, build.dist_scripts)
+ names = create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, b.dist_scripts)
else:
print('Dist currently only works with Git or Mercurial repos')
return 1
if names is None:
return 1
- error_count = 0
- for name in names:
- rc = check_dist(name, meson_command, priv_dir) # Check only one.
- if rc == 0:
+ # Check only one.
+ rc = check_dist(names[0], meson_command, bld_root, priv_dir)
+ if rc == 0:
+ for name in names:
create_hash(name)
- error_count += rc
- return 1 if error_count else 0
+ return rc
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 585a5bb..1223b2c 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -957,7 +957,10 @@ def expand_arguments(args):
return None
return expended_args
-def Popen_safe(args, write=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs):
+def Popen_safe(args: typing.List[str], write: typing.Optional[str] = None,
+ stdout: typing.Union[typing.BinaryIO, int] = subprocess.PIPE,
+ stderr: typing.Union[typing.BinaryIO, int] = subprocess.PIPE,
+ **kwargs: typing.Any) -> typing.Tuple[subprocess.Popen, str, str]:
import locale
encoding = locale.getpreferredencoding()
if sys.version_info < (3, 6) or not sys.stdout.encoding or encoding.upper() != 'UTF-8':
@@ -967,12 +970,16 @@ def Popen_safe(args, write=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
o, e = p.communicate(write)
return p, o, e
-def Popen_safe_legacy(args, write=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs):
+def Popen_safe_legacy(args: typing.List[str], write: typing.Optional[str] = None,
+ stdout: typing.Union[typing.BinaryIO, int] = subprocess.PIPE,
+ stderr: typing.Union[typing.BinaryIO, int] = subprocess.PIPE,
+ **kwargs: typing.Any) -> typing.Tuple[subprocess.Popen, str, str]:
p = subprocess.Popen(args, universal_newlines=False, close_fds=False,
stdout=stdout, stderr=stderr, **kwargs)
+ input_ = None # type: typing.Optional[bytes]
if write is not None:
- write = write.encode('utf-8')
- o, e = p.communicate(write)
+ input_ = write.encode('utf-8')
+ o, e = p.communicate(input_)
if o is not None:
if sys.stdout.encoding:
o = o.decode(encoding=sys.stdout.encoding, errors='replace').replace('\r\n', '\n')
@@ -1306,3 +1313,58 @@ class LibType(Enum):
STATIC = 1
PREFER_SHARED = 2
PREFER_STATIC = 3
+
+
+class ProgressBarFallback:
+ '''Fallback progress bar implementation when tqdm is not found'''
+ def __init__(self, iterable=None, total=None, bar_type=None, desc=None):
+ if iterable is not None:
+ self.iterable = iter(iterable)
+ return
+ self.total = total
+ self.done = 0
+ self.printed_dots = 0
+ if self.total and bar_type == 'download':
+ print('Download size:', self.total)
+ if desc:
+ print('{}: '.format(desc), end='')
+
+ # Pretend to be an iterator when called as one and don't print any
+ # progress
+ def __iter__(self):
+ return self.iterable
+
+ def __next__(self):
+ return next(self.iterable)
+
+ def print_dot(self):
+ print('.', end='')
+ sys.stdout.flush()
+ self.printed_dots += 1
+
+ def update(self, progress):
+ self.done += progress
+ if not self.total:
+ # Just print one dot per call if we don't have a total length
+ self.print_dot()
+ return
+ ratio = int(self.done / self.total * 10)
+ while self.printed_dots < ratio:
+ self.print_dot()
+
+ def close(self):
+ print('')
+
+try:
+ from tqdm import tqdm
+
+ class ProgressBar(tqdm):
+ def __init__(self, *args, bar_type=None, **kwargs):
+ if bar_type == 'download':
+ kwargs.update({'unit': 'bytes', 'leave': True})
+ else:
+ kwargs.update({'leave': False})
+ kwargs['ncols'] = 100
+ super().__init__(*args, **kwargs)
+except ImportError:
+ ProgressBar = ProgressBarFallback
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index c94f1bf..06214ad 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -22,7 +22,7 @@ import shutil
from . import mesonlib
from . import mlog
-from . import mconf, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata
+from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata
from .mesonlib import MesonException
from .environment import detect_msys2_arch
from .wrap import wraptool
@@ -44,6 +44,8 @@ class CommandLineParser:
help_msg='Configure the project')
self.add_command('configure', mconf.add_arguments, mconf.run,
help_msg='Change project options',)
+ self.add_command('dist', mdist.add_arguments, mdist.run,
+ help_msg='Generate release archive',)
self.add_command('install', minstall.add_arguments, minstall.run,
help_msg='Install the project')
self.add_command('introspect', mintro.add_arguments, mintro.run,
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index e81a8e1..1d30149 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -229,31 +229,33 @@ def list_buildoptions(coredata: cdata.CoreData) -> List[dict]:
core_options = {k: o for k, o in coredata.builtins.items() if k in core_option_names}
add_keys(optlist, core_options, 'core')
- add_keys(optlist, coredata.builtins_per_machine.host, 'core (for host machine)')
+ add_keys(optlist, coredata.builtins_per_machine.host, 'core', machine='host')
add_keys(
optlist,
{'build.' + k: o for k, o in coredata.builtins_per_machine.build.items()},
- 'core (for build machine)',
+ 'core',
+ machine='build',
)
add_keys(optlist, coredata.backend_options, 'backend')
add_keys(optlist, coredata.base_options, 'base')
- add_keys(optlist, coredata.compiler_options.host, 'compiler (for host machine)')
+ add_keys(optlist, coredata.compiler_options.host, 'compiler', machine='host')
add_keys(
optlist,
{'build.' + k: o for k, o in coredata.compiler_options.build.items()},
- 'compiler (for build machine)',
+ 'compiler',
+ machine='build',
)
add_keys(optlist, dir_options, 'directory')
add_keys(optlist, coredata.user_options, 'user')
add_keys(optlist, test_options, 'test')
return optlist
-def add_keys(optlist, options: Dict[str, cdata.UserOption], section):
+def add_keys(optlist, options: Dict[str, cdata.UserOption], section: str, machine: str = 'any'):
keys = list(options.keys())
keys.sort()
for key in keys:
opt = options[key]
- optdict = {'name': key, 'value': opt.value, 'section': section}
+ optdict = {'name': key, 'value': opt.value, 'section': section, 'machine': machine}
if isinstance(opt, cdata.UserStringOption):
typestr = 'string'
elif isinstance(opt, cdata.UserBooleanOption):
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index aa815c7..1ee98cc 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -23,7 +23,6 @@ import subprocess
from .. import build
from .. import mlog
from .. import mesonlib
-from .. import compilers
from .. import interpreter
from . import GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget
from . import get_include_args
@@ -604,7 +603,7 @@ class GnomeModule(ExtensionModule):
cflags += state.project_args[lang]
if 'b_sanitize' in compiler.base_options:
sanitize = state.environment.coredata.base_options['b_sanitize'].value
- cflags += compilers.sanitizer_compile_args(sanitize)
+ cflags += compiler.sanitizer_compile_args(sanitize)
sanitize = sanitize.split(',')
# These must be first in ldflags
if 'address' in sanitize:
@@ -615,7 +614,7 @@ class GnomeModule(ExtensionModule):
internal_ldflags += ['-lubsan']
# FIXME: Linking directly to lib*san is not recommended but g-ir-scanner
# does not understand -f LDFLAGS. https://bugzilla.gnome.org/show_bug.cgi?id=783892
- # ldflags += compilers.sanitizer_link_args(sanitize)
+ # ldflags += compiler.sanitizer_link_args(sanitize)
return cflags, internal_ldflags, external_ldflags
@@ -913,6 +912,7 @@ This will become a hard error in the future.''')
rv = [inscript, pottarget, potarget]
return ModuleReturnValue(None, rv)
+ @FeatureNewKwargs('gnome.gtkdoc', '0.52.0', ['check'])
@FeatureNewKwargs('gnome.gtkdoc', '0.48.0', ['c_args'])
@FeatureNewKwargs('gnome.gtkdoc', '0.48.0', ['module_version'])
@FeatureNewKwargs('gnome.gtkdoc', '0.37.0', ['namespace', 'mode'])
@@ -1019,10 +1019,26 @@ This will become a hard error in the future.''')
args += self._unpack_args('--ignore-headers=', 'ignore_headers', kwargs)
args += self._unpack_args('--installdir=', 'install_dir', kwargs)
args += self._get_build_args(kwargs, state, depends)
- res = [build.RunTarget(targetname, command[0], command[1:] + args, depends, state.subdir, state.subproject)]
+ custom_kwargs = {'output': modulename + '-decl.txt',
+ 'command': command + args,
+ 'depends': depends,
+ 'build_always_stale': True,
+ }
+ custom_target = build.CustomTarget(targetname, state.subdir, state.subproject, custom_kwargs)
+ alias_target = build.AliasTarget(targetname, [custom_target], state.subdir, state.subproject)
+ if kwargs.get('check', False):
+ check_cmd = self.interpreter.find_program_impl('gtkdoc-check')
+ check_env = ['DOC_MODULE=' + modulename,
+ 'DOC_MAIN_SGML_FILE=' + main_file]
+ check_args = [targetname + '-check', check_cmd]
+ check_kwargs = {'env': check_env,
+ 'workdir': os.path.join(state.environment.get_build_dir(), state.subdir),
+ 'depends': custom_target}
+ self.interpreter.add_test(state.current_node, check_args, check_kwargs, True)
+ res = [custom_target, alias_target]
if kwargs.get('install', True):
res.append(build.RunScript(command, args))
- return ModuleReturnValue(None, res)
+ return ModuleReturnValue(custom_target, res)
def _get_build_args(self, kwargs, state, depends):
args = []
diff --git a/mesonbuild/modules/unstable_kconfig.py b/mesonbuild/modules/unstable_kconfig.py
index 1639eed..6685710 100644
--- a/mesonbuild/modules/unstable_kconfig.py
+++ b/mesonbuild/modules/unstable_kconfig.py
@@ -54,15 +54,16 @@ class KconfigModule(ExtensionModule):
raise InvalidCode('load takes only one file input.')
s = sources[0]
+ is_built = False
if isinstance(s, mesonlib.File):
- # kconfig input is processed at "meson setup" time, not during
- # the build, so it cannot reside in the build directory.
if s.is_built:
- raise InvalidCode('kconfig input must be a source file.')
- s = s.relative_name()
+ FeatureNew('kconfig.load() of built files', '0.52.0').use(state.subproject)
+ is_built = True
+ s = s.absolute_path(interpreter.environment.source_dir, interpreter.environment.build_dir)
+ else:
+ s = os.path.join(interpreter.environment.source_dir, s)
- s = os.path.join(interpreter.environment.source_dir, s)
- if s not in interpreter.build_def_files:
+ if s not in interpreter.build_def_files and not is_built:
interpreter.build_def_files.append(s)
return self._load_file(s)
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 253f4ab..dc5c9d1 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -14,6 +14,7 @@
# A tool to run tests in many different ways.
+from pathlib import Path
from collections import namedtuple
from copy import deepcopy
import argparse
@@ -426,18 +427,18 @@ def run_with_mono(fname: str) -> bool:
return False
def load_benchmarks(build_dir: str) -> typing.List['TestSerialisation']:
- datafile = os.path.join(build_dir, 'meson-private', 'meson_benchmark_setup.dat')
- if not os.path.isfile(datafile):
- raise TestException('Directory ${!r} does not seem to be a Meson build directory.'.format(build_dir))
- with open(datafile, 'rb') as f:
+ datafile = Path(build_dir) / 'meson-private' / 'meson_benchmark_setup.dat'
+ if not datafile.is_file():
+ raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
+ with datafile.open('rb') as f:
obj = typing.cast(typing.List['TestSerialisation'], pickle.load(f))
return obj
def load_tests(build_dir: str) -> typing.List['TestSerialisation']:
- datafile = os.path.join(build_dir, 'meson-private', 'meson_test_setup.dat')
- if not os.path.isfile(datafile):
- raise TestException('Directory ${!r} does not seem to be a Meson build directory.'.format(build_dir))
- with open(datafile, 'rb') as f:
+ datafile = Path(build_dir) / 'meson-private' / 'meson_test_setup.dat'
+ if not datafile.is_file():
+ raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
+ with datafile.open('rb') as f:
obj = typing.cast(typing.List['TestSerialisation'], pickle.load(f))
return obj
@@ -833,8 +834,9 @@ Timeout: %4d
return False
def test_suitable(self, test: 'TestSerialisation') -> bool:
- return (not self.options.include_suites or TestHarness.test_in_suites(test, self.options.include_suites)) \
- and not TestHarness.test_in_suites(test, self.options.exclude_suites)
+ return ((not self.options.include_suites or
+ TestHarness.test_in_suites(test, self.options.include_suites)) and not
+ TestHarness.test_in_suites(test, self.options.exclude_suites))
def get_tests(self) -> typing.List['TestSerialisation']:
if not self.tests:
@@ -849,6 +851,7 @@ Timeout: %4d
else:
tests = self.tests
+ # allow specifying test names like "meson test foo1 foo2", where test('foo1', ...)
if self.options.args:
tests = [t for t in tests if t.name in self.options.args]
@@ -975,7 +978,7 @@ def list_tests(th: TestHarness) -> bool:
return not tests
def rebuild_all(wd: str) -> bool:
- if not os.path.isfile(os.path.join(wd, 'build.ninja')):
+ if not (Path(wd) / 'build.ninja').is_file():
print('Only ninja backend is supported to rebuild tests before running them.')
return True
@@ -984,11 +987,9 @@ def rebuild_all(wd: str) -> bool:
print("Can't find ninja, can't rebuild test.")
return False
- p = subprocess.Popen([ninja, '-C', wd])
- p.communicate()
-
- if p.returncode != 0:
- print('Could not rebuild')
+ ret = subprocess.run([ninja, '-C', wd]).returncode
+ if ret != 0:
+ print('Could not rebuild {}'.format(wd))
return False
return True
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index cc4669c..9925f4e 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -413,9 +413,8 @@ def fix_darwin(fname, new_rpath, final_path, install_name_mappings):
subprocess.check_call(['install_name_tool', fname] + args,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
- except Exception:
- raise
- sys.exit(0)
+ except Exception as err:
+ raise SystemExit(err)
def fix_jar(fname):
subprocess.check_call(['jar', 'xfv', fname, 'META-INF/MANIFEST.MF'])
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 55f86bc..4b2a323 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -18,8 +18,9 @@ import urllib.request, os, hashlib, shutil, tempfile, stat
import subprocess
import sys
import configparser
+
from . import WrapMode
-from ..mesonlib import MesonException
+from ..mesonlib import ProgressBar, MesonException
try:
import ssl
@@ -278,24 +279,17 @@ class Resolver:
tmpfile.write(block)
hashvalue = h.hexdigest()
return hashvalue, tmpfile.name
- print('Download size:', dlsize)
- print('Downloading: ', end='')
sys.stdout.flush()
- printed_dots = 0
- downloaded = 0
+ progress_bar = ProgressBar(bar_type='download', total=dlsize,
+ desc='Downloading')
while True:
block = resp.read(blocksize)
if block == b'':
break
- downloaded += len(block)
h.update(block)
tmpfile.write(block)
- ratio = int(downloaded / dlsize * 10)
- while printed_dots < ratio:
- print('.', end='')
- sys.stdout.flush()
- printed_dots += 1
- print('')
+ progress_bar.update(len(block))
+ progress_bar.close()
hashvalue = h.hexdigest()
return hashvalue, tmpfile.name
diff --git a/run_project_tests.py b/run_project_tests.py
index 797e1a9..a161525 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import List, Tuple
+import typing
import itertools
import os
import subprocess
@@ -35,6 +35,7 @@ from mesonbuild import mtest
from mesonbuild.mesonlib import MachineChoice, stringlistify, Popen_safe
from mesonbuild.coredata import backendlist
import argparse
+import json
import xml.etree.ElementTree as ET
import time
import multiprocessing
@@ -108,18 +109,10 @@ def setup_commands(optbackend):
compile_commands, clean_commands, test_commands, install_commands, \
uninstall_commands = get_backend_commands(backend, do_debug)
-def get_relative_files_list_from_dir(fromdir):
- paths = []
- for (root, _, files) in os.walk(fromdir):
- reldir = os.path.relpath(root, start=fromdir)
- for f in files:
- path = os.path.join(reldir, f).replace('\\', '/')
- if path.startswith('./'):
- path = path[2:]
- paths.append(path)
- return paths
-
-def platform_fix_name(fname, compiler, env):
+def get_relative_files_list_from_dir(fromdir: Path) -> typing.List[Path]:
+ return [file.relative_to(fromdir) for file in fromdir.rglob('*') if file.is_file()]
+
+def platform_fix_name(fname: str, compiler, env) -> str:
# canonicalize compiler
if compiler in {'clang-cl', 'intel-cl'}:
canonical_compiler = 'msvc'
@@ -199,35 +192,36 @@ def platform_fix_name(fname, compiler, env):
return fname
-def validate_install(srcdir, installdir, compiler, env):
+def validate_install(srcdir: str, installdir: Path, compiler, env) -> str:
# List of installed files
- info_file = os.path.join(srcdir, 'installed_files.txt')
+ info_file = Path(srcdir) / 'installed_files.txt'
+ installdir = Path(installdir)
# If this exists, the test does not install any other files
- noinst_file = 'usr/no-installed-files'
- expected = {}
+ noinst_file = Path('usr/no-installed-files')
+ expected = {} # type: typing.Dict[Path, bool]
ret_msg = ''
# Generate list of expected files
- if os.path.exists(os.path.join(installdir, noinst_file)):
+ if (installdir / noinst_file).is_file():
expected[noinst_file] = False
- elif os.path.exists(info_file):
- with open(info_file) as f:
+ elif info_file.is_file():
+ with info_file.open() as f:
for line in f:
line = platform_fix_name(line.strip(), compiler, env)
if line:
- expected[line] = False
+ expected[Path(line)] = False
# Check if expected files were found
for fname in expected:
- file_path = os.path.join(installdir, fname)
- if os.path.exists(file_path) or os.path.islink(file_path):
+ file_path = installdir / fname
+ if file_path.is_file() or file_path.is_symlink():
expected[fname] = True
for (fname, found) in expected.items():
if not found:
- ret_msg += 'Expected file {0} missing.\n'.format(fname)
+ ret_msg += 'Expected file {} missing.\n'.format(fname)
# Check if there are any unexpected files
found = get_relative_files_list_from_dir(installdir)
for fname in found:
if fname not in expected:
- ret_msg += 'Extra file {0} found.\n'.format(fname)
+ ret_msg += 'Extra file {} found.\n'.format(fname)
if ret_msg != '':
ret_msg += '\nInstall dir contents:\n'
for i in found:
@@ -348,6 +342,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen
compile_commands, clean_commands, install_commands, uninstall_commands = commands
test_args = parse_test_args(testdir)
gen_start = time.time()
+ setup_env = None
# Configure in-process
if pass_prefix_to_test(testdir):
gen_args = ['--prefix', '/usr']
@@ -362,7 +357,15 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen
crossfile = os.path.join(testdir, 'crossfile.ini')
if os.path.exists(crossfile):
gen_args.extend(['--cross-file', crossfile])
- (returncode, stdo, stde) = run_configure(gen_args)
+ setup_env_file = os.path.join(testdir, 'setup_env.json')
+ if os.path.exists(setup_env_file):
+ setup_env = os.environ.copy()
+ with open(setup_env_file, 'r') as fp:
+ data = json.load(fp)
+ for key, val in data.items():
+ val = val.replace('@ROOT@', os.path.abspath(testdir))
+ setup_env[key] = val
+ (returncode, stdo, stde) = run_configure(gen_args, env=setup_env)
try:
logfile = Path(test_build_dir, 'meson-logs', 'meson-log.txt')
mesonlog = logfile.open(errors='ignore', encoding='utf-8').read()
@@ -435,7 +438,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen
return TestResult(validate_install(testdir, install_dir, compiler, builddata.environment),
BuildStep.validate, stdo, stde, mesonlog, gen_time, build_time, test_time)
-def gather_tests(testdir: Path) -> List[Path]:
+def gather_tests(testdir: Path) -> typing.List[Path]:
test_names = [t.name for t in testdir.glob('*') if t.is_dir()]
test_names = [t for t in test_names if not t.startswith('.')] # Filter non-tests files (dot files, etc)
test_nums = [(int(t.split()[0]), t) for t in test_names]
@@ -588,7 +591,7 @@ def should_skip_rust() -> bool:
return True
return False
-def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
+def detect_tests_to_run(only: typing.List[str]) -> typing.List[typing.Tuple[str, typing.List[Path], bool]]:
"""
Parameters
----------
@@ -601,10 +604,8 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
tests to run
"""
- ninja_fortran_compiler = shutil.which('gfortran') or shutil.which('flang') or shutil.which('pgfortran') or (not mesonlib.is_windows() and shutil.which('ifort'))
- ninja_fortran = backend is Backend.ninja and ninja_fortran_compiler
- vs_fortran = mesonlib.is_windows() and backend is Backend.vs and shutil.which('ifort')
- skip_fortran = not(ninja_fortran or vs_fortran)
+ skip_fortran = not(shutil.which('gfortran') or shutil.which('flang') or
+ shutil.which('pgfortran') or shutil.which('ifort'))
# Name, subdirectory, skip condition.
all_tests = [
@@ -627,7 +628,7 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
('d', 'd', backend is not Backend.ninja or not have_d_compiler()),
('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler()),
('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler()),
- ('fortran', 'fortran', skip_fortran),
+ ('fortran', 'fortran', skip_fortran or backend != Backend.ninja),
('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')),
('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')),
('python3', 'python3', backend is not Backend.ninja),
@@ -644,14 +645,14 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
gathered_tests = [(name, gather_tests(Path('test cases', subdir)), skip) for name, subdir, skip in all_tests]
return gathered_tests
-def run_tests(all_tests, log_name_base, failfast, extra_args):
+def run_tests(all_tests, log_name_base, failfast: bool, extra_args):
global logfile
txtname = log_name_base + '.txt'
with open(txtname, 'w', encoding='utf-8', errors='ignore') as lf:
logfile = lf
return _run_tests(all_tests, log_name_base, failfast, extra_args)
-def _run_tests(all_tests, log_name_base, failfast, extra_args):
+def _run_tests(all_tests, log_name_base, failfast: bool, extra_args):
global stop, executor, futures, system_compiler
xmlname = log_name_base + '.xml'
junit_root = ET.Element('testsuites')
@@ -757,8 +758,8 @@ def _run_tests(all_tests, log_name_base, failfast, extra_args):
stdeel = ET.SubElement(current_test, 'system-err')
stdeel.text = result.stde
- if failfast and failing_tests > 0:
- break
+ if failfast and failing_tests > 0:
+ break
print("\nTotal configuration time: %.2fs" % conf_time)
print("Total build time: %.2fs" % build_time)
diff --git a/run_tests.py b/run_tests.py
index 051b91e..6a42681 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -34,11 +34,13 @@ from mesonbuild import mlog
from mesonbuild.environment import Environment, detect_ninja
from mesonbuild.coredata import backendlist
-def guess_backend(backend, msbuild_exe):
+def guess_backend(backend, msbuild_exe: str):
# Auto-detect backend if unspecified
backend_flags = []
if backend is None:
- if msbuild_exe is not None and mesonlib.is_windows():
+ if (msbuild_exe is not None and
+ mesonlib.is_windows() and not
+ (os.environ.get('CC') == 'icl' or os.environ.get('CXX') == 'icl' or os.environ.get('FC') == 'ifort')):
backend = 'vs' # Meson will auto-detect VS version to use
else:
backend = 'ninja'
@@ -222,28 +224,33 @@ def clear_meson_configure_class_caches():
mesonbuild.dependencies.PkgConfigDependency.pkgbin_cache = {}
mesonbuild.dependencies.PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None)
-def run_configure_inprocess(commandlist):
+def run_configure_inprocess(commandlist, env=None):
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
old_stderr = sys.stderr
sys.stderr = mystderr = StringIO()
+ old_environ = os.environ.copy()
+ if env is not None:
+ os.environ.update(env)
try:
returncode = mesonmain.run(commandlist, get_meson_script())
finally:
sys.stdout = old_stdout
sys.stderr = old_stderr
clear_meson_configure_class_caches()
+ os.environ.clear()
+ os.environ.update(old_environ)
return returncode, mystdout.getvalue(), mystderr.getvalue()
-def run_configure_external(full_command):
- pc, o, e = mesonlib.Popen_safe(full_command)
+def run_configure_external(full_command, env=None):
+ pc, o, e = mesonlib.Popen_safe(full_command, env=env)
return pc.returncode, o, e
-def run_configure(commandlist):
+def run_configure(commandlist, env=None):
global meson_exe
if meson_exe:
- return run_configure_external(meson_exe + commandlist)
- return run_configure_inprocess(commandlist)
+ return run_configure_external(meson_exe + commandlist, env=env)
+ return run_configure_inprocess(commandlist, env=env)
def print_system_info():
print(mlog.bold('System information.').get_text(mlog.colorize_console))
diff --git a/run_unittests.py b/run_unittests.py
index 93c9083..0bd2c02 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -30,6 +30,8 @@ import functools
import io
import operator
import threading
+import urllib.error
+import urllib.request
from itertools import chain
from unittest import mock
from configparser import ConfigParser
@@ -66,6 +68,10 @@ from run_tests import (
run_configure_inprocess, run_mtest_inprocess
)
+
+URLOPEN_TIMEOUT = 5
+
+
def get_dynamic_section_entry(fname, entry):
if is_cygwin() or is_osx():
raise unittest.SkipTest('Test only applicable to ELF platforms')
@@ -1126,10 +1132,10 @@ class DataTests(unittest.TestCase):
if f not in exceptions:
self.assertIn(f, toc)
- def test_syntax_highlighting_files(self):
+ def test_vim_syntax_highlighting(self):
'''
- Ensure that syntax highlighting files were updated for new functions in
- the global namespace in build files.
+ Ensure that vim syntax highlighting files were updated for new
+ functions in the global namespace in build files.
'''
env = get_fake_env()
interp = Interpreter(FakeBuild(env), mock=True)
@@ -1138,6 +1144,41 @@ class DataTests(unittest.TestCase):
defined = set([a.strip() for a in res.group().split('\\')][1:])
self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys())))
+ def test_json_grammar_syntax_highlighting(self):
+ '''
+ Ensure that syntax highlighting JSON grammar written by TingPing was
+ updated for new functions in the global namespace in build files.
+ https://github.com/TingPing/language-meson/
+ '''
+ env = get_fake_env()
+ interp = Interpreter(FakeBuild(env), mock=True)
+ url = 'https://raw.githubusercontent.com/TingPing/language-meson/master/grammars/meson.json'
+ try:
+ # Use a timeout to avoid blocking forever in case the network is
+ # slow or unavailable in a weird way
+ r = urllib.request.urlopen(url, timeout=URLOPEN_TIMEOUT)
+ except urllib.error.URLError as e:
+ # Skip test when network is not available, such as during packaging
+ # by a distro or Flatpak
+ if not isinstance(e, urllib.error.HTTPError):
+ raise unittest.SkipTest('Network unavailable')
+ # Don't fail the test if github is down, but do fail if 4xx
+ if e.code >= 500:
+ raise unittest.SkipTest('Server error ' + str(e.code))
+ raise e
+ # On Python 3.5, we must decode bytes to string. Newer versions don't require that.
+ grammar = json.loads(r.read().decode('utf-8', 'surrogatepass'))
+ for each in grammar['patterns']:
+ if 'name' in each and each['name'] == 'support.function.builtin.meson':
+ # The string is of the form: (?x)\\b(func1|func2|...\n)\\b\\s*(?=\\() and
+ # we convert that to [func1, func2, ...] without using regex to parse regex
+ funcs = set(each['match'].split('\\b(')[1].split('\n')[0].split('|'))
+ if 'name' in each and each['name'] == 'support.variable.meson':
+ # \\b(builtin1|builtin2...)\\b
+ builtin = set(each['match'].split('\\b(')[1].split(')\\b')[0].split('|'))
+ self.assertEqual(builtin, set(interp.builtin.keys()))
+ self.assertEqual(funcs, set(interp.funcs.keys()))
+
def test_all_functions_defined_in_ast_interpreter(self):
'''
Ensure that the all functions defined in the Interpreter are also defined
@@ -2369,13 +2410,21 @@ int main(int argc, char **argv) {
return 0;
}
''')
+ xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz')
+ xz_checksumfile = xz_distfile + '.sha256sum'
+ zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip')
+ zip_checksumfile = zip_distfile + '.sha256sum'
vcs_init(project_dir)
self.init(project_dir)
self.build('dist')
- distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz')
- checksumfile = distfile + '.sha256sum'
- self.assertPathExists(distfile)
- self.assertPathExists(checksumfile)
+ self.assertPathExists(xz_distfile)
+ self.assertPathExists(xz_checksumfile)
+ self.assertPathDoesNotExist(zip_distfile)
+ self.assertPathDoesNotExist(zip_checksumfile)
+ self._run(self.meson_command + ['dist', '--formats', 'zip'],
+ workdir=self.builddir)
+ self.assertPathExists(zip_distfile)
+ self.assertPathExists(zip_checksumfile)
def test_rpath_uses_ORIGIN(self):
'''
@@ -2630,6 +2679,7 @@ int main(int argc, char **argv) {
'section': 'user',
'type': 'array',
'value': ['foo', 'bar'],
+ 'machine': 'any',
}
tdir = os.path.join(self.unit_test_dir, '19 array option')
self.init(tdir)
@@ -2655,6 +2705,7 @@ int main(int argc, char **argv) {
'section': 'user',
'type': 'array',
'value': ['foo', 'bar'],
+ 'machine': 'any',
}
tdir = os.path.join(self.unit_test_dir, '19 array option')
self.init(tdir)
@@ -2680,6 +2731,7 @@ int main(int argc, char **argv) {
'section': 'user',
'type': 'array',
'value': [],
+ 'machine': 'any',
}
tdir = os.path.join(self.unit_test_dir, '19 array option')
self.init(tdir, extra_args='-Dlist=')
@@ -3496,6 +3548,7 @@ recommended as it is not supported on some platforms''')
('section', str),
('type', str),
('description', str),
+ ('machine', str),
]
buildoptions_typelist = [
@@ -3506,6 +3559,9 @@ recommended as it is not supported on some platforms''')
('array', list, []),
]
+ buildoptions_sections = ['core', 'backend', 'base', 'compiler', 'directory', 'user', 'test']
+ buildoptions_machines = ['any', 'build', 'host']
+
dependencies_typelist = [
('name', str),
('compile_args', list),
@@ -3561,6 +3617,8 @@ recommended as it is not supported on some platforms''')
valid_type = True
break
+ self.assertIn(i['section'], buildoptions_sections)
+ self.assertIn(i['machine'], buildoptions_machines)
self.assertTrue(valid_type)
if i['name'] in buildopts_to_find:
self.assertEqual(i['value'], buildopts_to_find[i['name']])
@@ -6547,17 +6605,32 @@ def unset_envs():
if v in os.environ:
del os.environ[v]
+def convert_args(argv):
+ # If we got passed a list of tests, pass it on
+ pytest_args = ['-v'] if '-v' in argv else []
+ test_list = []
+ for arg in argv:
+ if arg.startswith('-'):
+ continue
+ # ClassName.test_name => 'ClassName and test_name'
+ if '.' in arg:
+ arg = ' and '.join(arg.split('.'))
+ test_list.append(arg)
+ if test_list:
+ pytest_args += ['-k', ' or '.join(test_list)]
+ return pytest_args
+
def main():
unset_envs()
- pytest_args = ['-n', 'auto', './run_unittests.py']
- if shutil.which('pytest-3'):
- return subprocess.run(['pytest-3'] + pytest_args).returncode
- elif shutil.which('pytest'):
- return subprocess.run(['pytest'] + pytest_args).returncode
try:
import pytest # noqa: F401
+ # Need pytest-xdist for `-n` arg
+ import xdist # noqa: F401
+ pytest_args = ['-n', 'auto', './run_unittests.py']
+ pytest_args += convert_args(sys.argv[1:])
return subprocess.run(python_command + ['-m', 'pytest'] + pytest_args).returncode
except ImportError:
+ print('pytest-xdist not found, using unittest instead')
pass
# All attempts at locating pytest failed, fall back to plain unittest.
cases = ['InternalTests', 'DataTests', 'AllPlatformTests', 'FailureTests',
diff --git a/setup.py b/setup.py
index 166f480..7d18afa 100644
--- a/setup.py
+++ b/setup.py
@@ -49,6 +49,7 @@ if sys.platform != 'win32':
if __name__ == '__main__':
setup(name='meson',
version=version,
+ extras_require={'progress': ['tqdm']},
packages=packages,
package_data=package_data,
entry_points=entries,
diff --git a/sideci.yml b/sider.yml
index 5c56196..5c56196 100644
--- a/sideci.yml
+++ b/sider.yml
diff --git a/test cases/cmake/10 cmake_module_path/cmake/FindSomethingLikePython.cmake b/test cases/cmake/10 cmake_module_path/cmake/FindSomethingLikePython.cmake
new file mode 100644
index 0000000..4a189bf
--- /dev/null
+++ b/test cases/cmake/10 cmake_module_path/cmake/FindSomethingLikePython.cmake
@@ -0,0 +1,24 @@
+cmake_policy(VERSION 3.7)
+
+if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
+ find_package(Python COMPONENTS Interpreter)
+else()
+ find_package(PythonInterp)
+endif()
+
+if(Python_FOUND OR PYTHONINTERP_FOUND)
+ set(SomethingLikePython_FOUND ON)
+ set(SomethingLikePython_EXECUTABLE ${Python_EXECUTABLE})
+
+ if(NOT DEFINED Python_VERSION)
+ set(Python_VERSION ${Python_VERSION_STRING})
+ endif()
+ if(NOT TARGET Python::Interpreter)
+ add_executable(Python::Interpreter IMPORTED)
+ set_target_properties(Python::Interpreter PROPERTIES
+ IMPORTED_LOCATION ${Python_EXECUTABLE}
+ VERSION ${Python_VERSION})
+ endif()
+else()
+ set(SomethingLikePython_FOUND OFF)
+endif()
diff --git a/test cases/cmake/10 cmake_module_path/meson.build b/test cases/cmake/10 cmake_module_path/meson.build
new file mode 100644
index 0000000..2259268
--- /dev/null
+++ b/test cases/cmake/10 cmake_module_path/meson.build
@@ -0,0 +1,17 @@
+# We use Python3 as it's the only thing guaranteed to be available on any platform Meson can run on (unlike Zlib in linuxlike/13 cmake dependency).
+
+project('user CMake find_package module using cmake_module_path',
+ meson_version: '>= 0.50.0')
+
+if not find_program('cmake', required: false).found()
+ error('MESON_SKIP_TEST cmake binary not available.')
+endif
+
+# NOTE: can't request Python3 via dependency('Python3', method: 'cmake')
+# Meson intercepts and wants "method: auto"
+
+# Try to find a dependency with a custom CMake module
+
+dependency('SomethingLikePython', required : true, method : 'cmake', cmake_module_path : 'cmake', modules: 'Python::Interpreter')
+
+dependency('SomethingLikePython', method : 'cmake', cmake_module_path : ['doesNotExist', 'cmake'], modules: 'Python::Interpreter')
diff --git a/test cases/cmake/10 generator expressions/main.cpp b/test cases/cmake/10 generator expressions/main.cpp
new file mode 100644
index 0000000..315c0f7
--- /dev/null
+++ b/test cases/cmake/10 generator expressions/main.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+#include <cmMod.hpp>
+
+using namespace std;
+
+int main() {
+ cmModClass obj("Hello");
+ cout << obj.getStr() << endl;
+ return 0;
+}
diff --git a/test cases/cmake/10 generator expressions/meson.build b/test cases/cmake/10 generator expressions/meson.build
new file mode 100644
index 0000000..ca08a3f
--- /dev/null
+++ b/test cases/cmake/10 generator expressions/meson.build
@@ -0,0 +1,12 @@
+project('cmakeSubTest', ['c', 'cpp'])
+
+cm = import('cmake')
+
+sub_pro = cm.subproject('cmMod')
+sub_dep = sub_pro.dependency('cmModLib')
+
+assert(sub_pro.target_list() == ['cmModLib'], 'There should be exactly one target')
+assert(sub_pro.target_type('cmModLib') == 'header_only', 'Target type should be header_only')
+
+exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep])
+test('test1', exe1)
diff --git a/test cases/cmake/10 generator expressions/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/10 generator expressions/subprojects/cmMod/CMakeLists.txt
new file mode 100644
index 0000000..dc4f9e4
--- /dev/null
+++ b/test cases/cmake/10 generator expressions/subprojects/cmMod/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmMod)
+set (CMAKE_CXX_STANDARD 14)
+
+include(GNUInstallDirs)
+
+add_library(cmModLib INTERFACE)
+
+target_compile_options(cmModLib
+ INTERFACE $<$<AND:$<CONFIG:Release>,$<CONFIG:Debug>>:-DCMAKE_FLAG_ERROR_A> # Check discard = false
+ INTERFACE "-DCMAKE_FLAG_REQUIRED_A"
+ INTERFACE $<$<AND:1,$<STREQUAL:asd,$<LOWER_CASE:AsD>>,$<NOT:$<EQUAL:4,2>>>:-DCMAKE_FLAG_REQUIRED_B>
+ INTERFACE $<$<VERSION_LESS:1.2.3,2.1.0>:-DCMAKE_FLAG_REQUIRED_C>
+)
+
+target_include_directories(cmModLib INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+target_compile_definitions(cmModLib INTERFACE -DCMAKE_COMPILER_DEFINE_STR="compDef")
diff --git a/test cases/cmake/10 generator expressions/subprojects/cmMod/include/cmMod.hpp b/test cases/cmake/10 generator expressions/subprojects/cmMod/include/cmMod.hpp
new file mode 100644
index 0000000..1f00107
--- /dev/null
+++ b/test cases/cmake/10 generator expressions/subprojects/cmMod/include/cmMod.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <string>
+
+#ifndef CMAKE_FLAG_REQUIRED_A
+#error "The flag CMAKE_FLAG_REQUIRED_A was not set"
+#endif
+
+#ifndef CMAKE_FLAG_REQUIRED_B
+#error "The flag CMAKE_FLAG_REQUIRED_B was not set"
+#endif
+
+#ifndef CMAKE_FLAG_REQUIRED_C
+#error "The flag CMAKE_FLAG_REQUIRED_C was not set"
+#endif
+
+#ifdef CMAKE_FLAG_ERROR_A
+#error "The flag CMAKE_FLAG_ERROR_A was set"
+#endif
+
+class cmModClass {
+ private:
+ std::string str;
+ public:
+ cmModClass(std::string foo) {
+ str = foo + " World ";
+ str += CMAKE_COMPILER_DEFINE_STR;
+ }
+
+ inline std::string getStr() const { return str; }
+};
diff --git a/test cases/cmake/9 header only/main.cpp b/test cases/cmake/9 header only/main.cpp
new file mode 100644
index 0000000..315c0f7
--- /dev/null
+++ b/test cases/cmake/9 header only/main.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+#include <cmMod.hpp>
+
+using namespace std;
+
+int main() {
+ cmModClass obj("Hello");
+ cout << obj.getStr() << endl;
+ return 0;
+}
diff --git a/test cases/cmake/9 header only/meson.build b/test cases/cmake/9 header only/meson.build
new file mode 100644
index 0000000..ca08a3f
--- /dev/null
+++ b/test cases/cmake/9 header only/meson.build
@@ -0,0 +1,12 @@
+project('cmakeSubTest', ['c', 'cpp'])
+
+cm = import('cmake')
+
+sub_pro = cm.subproject('cmMod')
+sub_dep = sub_pro.dependency('cmModLib')
+
+assert(sub_pro.target_list() == ['cmModLib'], 'There should be exactly one target')
+assert(sub_pro.target_type('cmModLib') == 'header_only', 'Target type should be header_only')
+
+exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep])
+test('test1', exe1)
diff --git a/test cases/cmake/9 header only/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/9 header only/subprojects/cmMod/CMakeLists.txt
new file mode 100644
index 0000000..f5d9a47
--- /dev/null
+++ b/test cases/cmake/9 header only/subprojects/cmMod/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmMod)
+set (CMAKE_CXX_STANDARD 14)
+
+add_definitions("-DDO_NOTHING_JUST_A_FLAG=1")
+
+add_library(cmModLib INTERFACE)
+set_target_properties(cmModLib PROPERTIES INTERFACE_COMPILE_OPTIONS "-DCMAKE_FLAG_MUST_BE_PRESENT")
+target_include_directories(cmModLib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include")
+target_compile_definitions(cmModLib INTERFACE -DCMAKE_COMPILER_DEFINE_STR="compDef")
diff --git a/test cases/cmake/9 header only/subprojects/cmMod/include/cmMod.hpp b/test cases/cmake/9 header only/subprojects/cmMod/include/cmMod.hpp
new file mode 100644
index 0000000..7ea72f7
--- /dev/null
+++ b/test cases/cmake/9 header only/subprojects/cmMod/include/cmMod.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <string>
+
+#ifndef CMAKE_FLAG_MUST_BE_PRESENT
+#error "The flag CMAKE_FLAG_MUST_BE_PRESENT was not set"
+#endif
+
+class cmModClass {
+ private:
+ std::string str;
+ public:
+ cmModClass(std::string foo) {
+ str = foo + " World ";
+ str += CMAKE_COMPILER_DEFINE_STR;
+ }
+
+ inline std::string getStr() const { return str; }
+};
diff --git a/test cases/common/122 shared module/module.c b/test cases/common/122 shared module/module.c
index 181b760..9c8774d 100644
--- a/test cases/common/122 shared module/module.c
+++ b/test cases/common/122 shared module/module.c
@@ -27,6 +27,19 @@ fptr find_any_f (const char *name) {
#include <windows.h>
#include <tlhelp32.h>
+static wchar_t*
+win32_get_last_error (void)
+{
+ wchar_t *msg = NULL;
+
+ FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_IGNORE_INSERTS
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError (), 0,
+ (LPWSTR) &msg, 0, NULL);
+ return msg;
+}
+
/* Unlike Linux and OS X, when a library is loaded, all the symbols aren't
* loaded into a single namespace. You must fetch the symbol by iterating over
* all loaded modules. Code for finding the function from any of the loaded
@@ -38,7 +51,8 @@ fptr find_any_f (const char *name) {
snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
if (snapshot == (HANDLE) -1) {
- printf("Could not get snapshot\n");
+ wchar_t *msg = win32_get_last_error ();
+ printf("Could not get snapshot: %S\n", msg);
return 0;
}
diff --git a/test cases/common/122 shared module/prog.c b/test cases/common/122 shared module/prog.c
index 2b63840..8b56d93 100644
--- a/test cases/common/122 shared module/prog.c
+++ b/test cases/common/122 shared module/prog.c
@@ -8,7 +8,7 @@ typedef int (*fptr) (void);
#include <windows.h>
-wchar_t*
+static wchar_t*
win32_get_last_error (void)
{
wchar_t *msg = NULL;
diff --git a/test cases/common/13 pch/c/meson.build b/test cases/common/13 pch/c/meson.build
index fe4ac68..6fba15b 100644
--- a/test cases/common/13 pch/c/meson.build
+++ b/test cases/common/13 pch/c/meson.build
@@ -1,8 +1,14 @@
cc = meson.get_compiler('c')
cc_id = cc.get_id()
+
if cc_id == 'lcc'
error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.')
endif
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
exe = executable('prog', 'prog.c',
c_pch : 'pch/prog.h')
diff --git a/test cases/common/13 pch/cpp/prog.cc b/test cases/common/13 pch/cpp/prog.cc
index 629d880..ea258c6 100644
--- a/test cases/common/13 pch/cpp/prog.cc
+++ b/test cases/common/13 pch/cpp/prog.cc
@@ -1,8 +1,11 @@
+// Note: if using PGI compilers, you will need to add #include "prog.hh"
+// even though you're using precompiled headers.
void func() {
std::cout << "This is a function that fails to compile if iostream is not included."
<< std::endl;
}
int main(int argc, char **argv) {
+ func();
return 0;
}
diff --git a/test cases/common/13 pch/generated/meson.build b/test cases/common/13 pch/generated/meson.build
index 1ef771b..ba06bce 100644
--- a/test cases/common/13 pch/generated/meson.build
+++ b/test cases/common/13 pch/generated/meson.build
@@ -1,9 +1,15 @@
cc = meson.get_compiler('c')
cc_id = cc.get_id()
+
if cc_id == 'lcc'
error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.')
endif
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
generated_customTarget = custom_target('makeheader',
output: 'generated_customTarget.h',
command : [find_program('gen_custom.py'), '@OUTPUT0@'])
diff --git a/test cases/common/13 pch/meson.build b/test cases/common/13 pch/meson.build
index 4438c9e..334afc5 100644
--- a/test cases/common/13 pch/meson.build
+++ b/test cases/common/13 pch/meson.build
@@ -1,4 +1,12 @@
-project('pch test', 'c', 'cpp')
+project('pch test', 'c', 'cpp',
+ meson_version: '>= 0.46.0')
+
+cc = meson.get_compiler('c')
+cc_id = cc.get_id()
+
+if cc_id == 'pgi'
+ error('MESON_SKIP_TEST: PGI compiler does support PCH, however, PGI cannot tolerate spaces in the --pch_dir path and Meson run_project_tests.py uses spaces in temporary build path names. If this test is run individually with no spaces in build path, it will pass.')
+endif
subdir('c')
subdir('cpp')
diff --git a/test cases/common/13 pch/mixed/meson.build b/test cases/common/13 pch/mixed/meson.build
index cbb7bac..266e7a5 100644
--- a/test cases/common/13 pch/mixed/meson.build
+++ b/test cases/common/13 pch/mixed/meson.build
@@ -1,3 +1,11 @@
+cc = meson.get_compiler('c')
+cc_id = cc.get_id()
+
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
exe = executable(
'prog',
files('main.cc', 'func.c'),
diff --git a/test cases/common/13 pch/withIncludeDirectories/meson.build b/test cases/common/13 pch/withIncludeDirectories/meson.build
index 68e544b..95f7888 100644
--- a/test cases/common/13 pch/withIncludeDirectories/meson.build
+++ b/test cases/common/13 pch/withIncludeDirectories/meson.build
@@ -1,9 +1,15 @@
cc = meson.get_compiler('c')
cc_id = cc.get_id()
+
if cc_id == 'lcc'
error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.')
endif
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
exe = executable('prog', 'prog.c',
include_directories: 'include',
c_pch : 'pch/prog.h')
diff --git a/test cases/common/164 disabler/meson.build b/test cases/common/164 disabler/meson.build
index a1763d2..9437ace 100644
--- a/test cases/common/164 disabler/meson.build
+++ b/test cases/common/164 disabler/meson.build
@@ -33,6 +33,7 @@ assert(number == 2, 'If found handled incorrectly, value should be 2 but is @0@'
dep = dependency('notfounddep', required : false, disabler : true)
app = executable('myapp', 'notfound.c', dependencies : [dep])
+app = executable('myapp', 'notfound.c', dependencies : [[dep]])
cc = meson.get_compiler('c')
dep = cc.find_library('notfounddep', required : false, disabler : true)
diff --git a/test cases/common/190 openmp/meson.build b/test cases/common/190 openmp/meson.build
index 71bf697..a1154c2 100644
--- a/test cases/common/190 openmp/meson.build
+++ b/test cases/common/190 openmp/meson.build
@@ -1,4 +1,4 @@
-project('openmp', 'c', 'cpp')
+project('openmp', 'c')
cc = meson.get_compiler('c')
if cc.get_id() == 'gcc' and cc.version().version_compare('<4.2.0')
@@ -21,21 +21,22 @@ if host_machine.system() == 'darwin'
endif
openmp = dependency('openmp')
+env = environment()
+env.set('OMP_NUM_THREADS', '2')
exec = executable('exec',
'main.c',
dependencies : [openmp])
-
-execpp = executable('execpp',
- 'main.cpp',
- dependencies : [openmp])
-
-env = environment()
-env.set('OMP_NUM_THREADS', '2')
-
test('OpenMP C', exec, env : env)
-test('OpenMP C++', execpp, env : env)
+if not(build_machine.system() == 'windows' and cc.get_id() == 'pgi')
+ if add_languages('cpp', required : false)
+ execpp = executable('execpp',
+ 'main.cpp',
+ dependencies : [openmp])
+ test('OpenMP C++', execpp, env : env)
+ endif
+endif
if add_languages('fortran', required : false)
# Mixing compilers (msvc/clang with gfortran) does not seem to work on Windows.
diff --git a/test cases/common/223 source set realistic example/meson.build b/test cases/common/223 source set realistic example/meson.build
index f983e8b..2a9475a 100644
--- a/test cases/common/223 source set realistic example/meson.build
+++ b/test cases/common/223 source set realistic example/meson.build
@@ -2,6 +2,12 @@
# modules, inspired by QEMU's build system
project('sourceset-example', 'cpp')
+
+cppid = meson.get_compiler('cpp').get_id()
+if cppid == 'pgi'
+ error('MESON_SKIP_TEST: Even PGI 19.4 that claims C++17 full support, cannot handle auto x = y syntax used in this test.')
+endif
+
ss = import('sourceset')
kconfig = import('unstable-kconfig')
diff --git a/test cases/common/29 find program/meson.build b/test cases/common/29 find program/meson.build
index ba5386d..983b7b4 100644
--- a/test cases/common/29 find program/meson.build
+++ b/test cases/common/29 find program/meson.build
@@ -18,3 +18,12 @@ else
e = executable('prog', generated)
test('external exe', e)
endif
+
+prog = find_program('print-version.py', version : '>=2.0', required : false)
+assert(not prog.found(), 'Version should be too old')
+
+prog = find_program('print-version.py', version : '>=1.0')
+assert(prog.found(), 'Program version should match')
+
+prog = find_program('print-version-with-prefix.py', version : '>=1.0')
+assert(prog.found(), 'Program version should match')
diff --git a/test cases/common/29 find program/print-version-with-prefix.py b/test cases/common/29 find program/print-version-with-prefix.py
new file mode 100644
index 0000000..520e0ba
--- /dev/null
+++ b/test cases/common/29 find program/print-version-with-prefix.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python3
+
+import sys
+
+if len(sys.argv) != 2 or sys.argv[1] != '--version':
+ exit(1)
+
+print('Version: 1.0')
diff --git a/test cases/common/29 find program/print-version.py b/test cases/common/29 find program/print-version.py
new file mode 100644
index 0000000..4a78e5b
--- /dev/null
+++ b/test cases/common/29 find program/print-version.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python3
+
+import sys
+
+if len(sys.argv) != 2 or sys.argv[1] != '--version':
+ exit(1)
+
+print('1.0')
diff --git a/test cases/fortran/13 coarray/meson.build b/test cases/fortran/13 coarray/meson.build
index 3160aa6..3e52dde 100644
--- a/test cases/fortran/13 coarray/meson.build
+++ b/test cases/fortran/13 coarray/meson.build
@@ -1,6 +1,13 @@
project('Fortran coarray', 'fortran',
meson_version: '>=0.50')
+fc = meson.get_compiler('fortran')
+fcid = fc.get_id()
+
+if ['pgi', 'flang'].contains(fcid)
+ error('MESON_SKIP_TEST: At least through PGI 19.4 and Flang 7.1 do not support Fortran Coarrays.')
+endif
+
# coarray is required because single-image fallback is an intrinsic feature
coarray = dependency('coarray', required : true)
diff --git a/test cases/fortran/14 fortran links c/meson.build b/test cases/fortran/14 fortran links c/meson.build
index 1ac47e4..a45f06f 100644
--- a/test cases/fortran/14 fortran links c/meson.build
+++ b/test cases/fortran/14 fortran links c/meson.build
@@ -1,5 +1,6 @@
project('Fortran calling C', 'fortran', 'c',
- meson_version: '>= 0.51.0')
+ meson_version: '>= 0.51.0',
+ default_options : ['default_library=static'])
ccid = meson.get_compiler('c').get_id()
if ccid == 'msvc' or ccid == 'clang-cl'
diff --git a/test cases/fortran/2 modules/meson.build b/test cases/fortran/2 modules/meson.build
index fb58b9d..791ae63 100644
--- a/test cases/fortran/2 modules/meson.build
+++ b/test cases/fortran/2 modules/meson.build
@@ -1,4 +1,5 @@
-project('modules', 'fortran')
+project('modules', 'fortran',
+ default_options : ['default_library=static'])
commented = library('commented', 'comment_mod.f90')
diff --git a/test cases/fortran/6 dynamic/meson.build b/test cases/fortran/6 dynamic/meson.build
index 244a38b..413223b 100644
--- a/test cases/fortran/6 dynamic/meson.build
+++ b/test cases/fortran/6 dynamic/meson.build
@@ -1,9 +1,11 @@
project('dynamic_fortran', 'fortran')
-if meson.get_compiler('fortran').get_id() == 'intel-cl'
- error('MESON_SKIP_TEST: Windows ifort does not use shared_library in a sane way')
+fcid = meson.get_compiler('fortran').get_id()
+if fcid == 'intel-cl' or (host_machine.system() == 'windows' and fcid == 'pgi')
+ error('MESON_SKIP_TEST: non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way')
# !DEC$ ATTRIBUTES DLLEXPORT must be used!
# https://software.intel.com/en-us/node/535306
+ # https://www.pgroup.com/resources/docs/19.4/x86/pgi-user-guide/index.htm#lib-dynlnk-bld-dll-fort
endif
dynamic = shared_library('dynamic', 'dynamic.f90')
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml b/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml
new file mode 100644
index 0000000..95f73ef
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar1/foobar-docs.sgml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY version SYSTEM "../version.xml">
+]>
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>Foolib Reference Manual</title>
+ <releaseinfo>
+ for Foobar &version;
+ </releaseinfo>
+ <authorgroup>
+ <author>
+ <firstname>Jonny</firstname>
+ <surname>Example</surname>
+ <affiliation>
+ <address>
+ <email>unknown@example.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2015</year>
+ <holder>Foobar corporation holdings ltd</holder>
+ </copyright>
+ </bookinfo>
+
+ <reference id="foobar">
+ <title>Foobar library</title>
+ <partintro>
+ <para>
+ This part documents Foobar libs.
+ </para>
+ </partintro>
+ <xi:include href="xml/foo.xml"/>
+ <xi:include href="../../include/bar.xml"/>
+ <xi:include href="xml/foo-version.xml"/>
+ </reference>
+
+</book>
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build b/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build
new file mode 100644
index 0000000..149c6e9
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build
@@ -0,0 +1,5 @@
+gnome.gtkdoc('foobar',
+ src_dir : inc,
+ main_sgml : 'foobar-docs.sgml',
+ content_files : [docbook, version_xml],
+ install : true)
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar2/foobar-docs.sgml b/test cases/frameworks/10 gtk-doc/doc/foobar2/foobar-docs.sgml
new file mode 100644
index 0000000..95f73ef
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar2/foobar-docs.sgml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY version SYSTEM "../version.xml">
+]>
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>Foolib Reference Manual</title>
+ <releaseinfo>
+ for Foobar &version;
+ </releaseinfo>
+ <authorgroup>
+ <author>
+ <firstname>Jonny</firstname>
+ <surname>Example</surname>
+ <affiliation>
+ <address>
+ <email>unknown@example.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2015</year>
+ <holder>Foobar corporation holdings ltd</holder>
+ </copyright>
+ </bookinfo>
+
+ <reference id="foobar">
+ <title>Foobar library</title>
+ <partintro>
+ <para>
+ This part documents Foobar libs.
+ </para>
+ </partintro>
+ <xi:include href="xml/foo.xml"/>
+ <xi:include href="../../include/bar.xml"/>
+ <xi:include href="xml/foo-version.xml"/>
+ </reference>
+
+</book>
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build b/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build
new file mode 100644
index 0000000..0b2faa0
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build
@@ -0,0 +1,6 @@
+gnome.gtkdoc('foobar2',
+ src_dir : inc,
+ main_sgml : 'foobar-docs.sgml',
+ content_files : [docbook, version_xml],
+ install : true,
+ install_dir : 'foobar2')
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar3/foobar-docs.sgml b/test cases/frameworks/10 gtk-doc/doc/foobar3/foobar-docs.sgml
new file mode 100644
index 0000000..95f73ef
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar3/foobar-docs.sgml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY version SYSTEM "../version.xml">
+]>
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>Foolib Reference Manual</title>
+ <releaseinfo>
+ for Foobar &version;
+ </releaseinfo>
+ <authorgroup>
+ <author>
+ <firstname>Jonny</firstname>
+ <surname>Example</surname>
+ <affiliation>
+ <address>
+ <email>unknown@example.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2015</year>
+ <holder>Foobar corporation holdings ltd</holder>
+ </copyright>
+ </bookinfo>
+
+ <reference id="foobar">
+ <title>Foobar library</title>
+ <partintro>
+ <para>
+ This part documents Foobar libs.
+ </para>
+ </partintro>
+ <xi:include href="xml/foo.xml"/>
+ <xi:include href="../../include/bar.xml"/>
+ <xi:include href="xml/foo-version.xml"/>
+ </reference>
+
+</book>
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar3/meson.build b/test cases/frameworks/10 gtk-doc/doc/foobar3/meson.build
new file mode 100644
index 0000000..0dce2f8
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar3/meson.build
@@ -0,0 +1,6 @@
+gnome.gtkdoc('foobar',
+ module_version : '3.0',
+ src_dir : inc,
+ main_sgml : 'foobar-docs.sgml',
+ content_files : [docbook, version_xml],
+ install : true)
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar4/foobar-docs.sgml b/test cases/frameworks/10 gtk-doc/doc/foobar4/foobar-docs.sgml
new file mode 100644
index 0000000..95f73ef
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar4/foobar-docs.sgml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY version SYSTEM "../version.xml">
+]>
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>Foolib Reference Manual</title>
+ <releaseinfo>
+ for Foobar &version;
+ </releaseinfo>
+ <authorgroup>
+ <author>
+ <firstname>Jonny</firstname>
+ <surname>Example</surname>
+ <affiliation>
+ <address>
+ <email>unknown@example.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+ <copyright>
+ <year>2015</year>
+ <holder>Foobar corporation holdings ltd</holder>
+ </copyright>
+ </bookinfo>
+
+ <reference id="foobar">
+ <title>Foobar library</title>
+ <partintro>
+ <para>
+ This part documents Foobar libs.
+ </para>
+ </partintro>
+ <xi:include href="xml/foo.xml"/>
+ <xi:include href="../../include/bar.xml"/>
+ <xi:include href="xml/foo-version.xml"/>
+ </reference>
+
+</book>
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar4/meson.build b/test cases/frameworks/10 gtk-doc/doc/foobar4/meson.build
new file mode 100644
index 0000000..959e507
--- /dev/null
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar4/meson.build
@@ -0,0 +1,7 @@
+gnome.gtkdoc('foobar2',
+ module_version : '3.0',
+ src_dir : inc,
+ main_sgml : 'foobar-docs.sgml',
+ content_files : [docbook, version_xml],
+ install : true,
+ install_dir : 'foobar3')
diff --git a/test cases/frameworks/10 gtk-doc/doc/meson.build b/test cases/frameworks/10 gtk-doc/doc/meson.build
index 019be94..c001f89 100644
--- a/test cases/frameworks/10 gtk-doc/doc/meson.build
+++ b/test cases/frameworks/10 gtk-doc/doc/meson.build
@@ -4,30 +4,7 @@ version_xml = configure_file(input : 'version.xml.in',
output : 'version.xml',
configuration : cdata)
-gnome.gtkdoc('foobar',
- src_dir : inc,
- main_sgml : 'foobar-docs.sgml',
- content_files : [docbook, version_xml],
- install : true)
-
-gnome.gtkdoc('foobar2',
- src_dir : inc,
- main_sgml : 'foobar-docs.sgml',
- content_files : [docbook, version_xml],
- install : true,
- install_dir : 'foobar2')
-
-gnome.gtkdoc('foobar',
- module_version : '3.0',
- src_dir : inc,
- main_sgml : 'foobar-docs.sgml',
- content_files : [docbook, version_xml],
- install : true)
-
-gnome.gtkdoc('foobar2',
- module_version : '3.0',
- src_dir : inc,
- main_sgml : 'foobar-docs.sgml',
- content_files : [docbook, version_xml],
- install : true,
- install_dir : 'foobar3')
+subdir('foobar1')
+subdir('foobar2')
+subdir('foobar3')
+subdir('foobar4')
diff --git a/test cases/kconfig/4 load_config builddir/meson.build b/test cases/kconfig/4 load_config builddir/meson.build
index 93136ba..1924d23 100644
--- a/test cases/kconfig/4 load_config builddir/meson.build
+++ b/test cases/kconfig/4 load_config builddir/meson.build
@@ -2,8 +2,8 @@ project('kconfig builddir test')
k = import('unstable-kconfig')
-configure_file(input: 'config', output: 'out-config', copy: true)
-conf = k.load(meson.build_root() / 'out-config')
+out_conf = configure_file(input: 'config', output: 'out-config', copy: true)
+conf = k.load(out_conf)
if not conf.has_key('CONFIG_IS_SET')
error('Expected CONFIG_IS_SET to be set, but it wasn\'t')
diff --git a/test cases/linuxlike/13 cmake dependency/cmake/FindImportedTarget.cmake b/test cases/linuxlike/13 cmake dependency/cmake/FindImportedTarget.cmake
new file mode 100644
index 0000000..d65c6fb
--- /dev/null
+++ b/test cases/linuxlike/13 cmake dependency/cmake/FindImportedTarget.cmake
@@ -0,0 +1,13 @@
+find_package(ZLIB)
+
+if(ZLIB_FOUND OR ZLIB_Found)
+ set(ImportedTarget_FOUND ON)
+ add_library(mesonTestLibDefs UNKNOWN IMPORTED)
+ set_property(TARGET mesonTestLibDefs PROPERTY IMPORTED_LOCATION ${ZLIB_LIBRARY})
+ set_property(TARGET mesonTestLibDefs PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIR})
+ set_property(TARGET mesonTestLibDefs APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS REQUIRED_MESON_FLAG1)
+ set_property(TARGET mesonTestLibDefs APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS $<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG>) # Error empty string
+ set_property(TARGET mesonTestLibDefs APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS REQUIRED_MESON_FLAG2)
+else()
+ set(ImportedTarget_FOUND OFF)
+endif()
diff --git a/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonTestDep/cmMesonTestDepConfig.cmake b/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonTestDep/cmMesonTestDepConfig.cmake
new file mode 100644
index 0000000..06a2060
--- /dev/null
+++ b/test cases/linuxlike/13 cmake dependency/cmake_pref_env/lib/cmake/cmMesonTestDep/cmMesonTestDepConfig.cmake
@@ -0,0 +1,9 @@
+find_package(ZLIB)
+
+if(ZLIB_FOUND OR ZLIB_Found)
+ set(cmMesonTestDep_FOUND ON)
+ set(cmMesonTestDep_LIBRARIES ${ZLIB_LIBRARY})
+ set(cmMesonTestDep_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
+else()
+ set(cmMesonTestDep_FOUND OFF)
+endif()
diff --git a/test cases/linuxlike/13 cmake dependency/meson.build b/test cases/linuxlike/13 cmake dependency/meson.build
index a18cd84..411b7a3 100644
--- a/test cases/linuxlike/13 cmake dependency/meson.build
+++ b/test cases/linuxlike/13 cmake dependency/meson.build
@@ -36,12 +36,22 @@ depf2 = dependency('ZLIB', required : false, method : 'cmake', modules : 'dfggh:
assert(depf2.found() == false, 'Invalid CMake targets should fail')
+# Try to find cmMesonTestDep in a custom prefix
+
+depPrefEnv = dependency('cmMesonTestDep', required : true, method : 'cmake')
+
# Try to find a dependency with a custom CMake module
depm1 = dependency('SomethingLikeZLIB', required : true, method : 'cmake', cmake_module_path : 'cmake')
depm2 = dependency('SomethingLikeZLIB', required : true, method : 'cmake', cmake_module_path : ['cmake'])
depm3 = dependency('SomethingLikeZLIB', required : true, cmake_module_path : 'cmake')
+# Test some edge cases with spaces, etc.
+
+testDep = dependency('ImportedTarget', required : true, method : 'cmake', cmake_module_path : 'cmake', modules: 'mesonTestLibDefs')
+testFlagSet = executable('testFlagSet', ['testFlagSet.c'], dependencies: [testDep])
+test('testFlagSetTest', testFlagSet)
+
# Try to compile a test that takes a dep and an include_directories
cc = meson.get_compiler('c')
diff --git a/test cases/linuxlike/13 cmake dependency/setup_env.json b/test cases/linuxlike/13 cmake dependency/setup_env.json
new file mode 100644
index 0000000..aa15374
--- /dev/null
+++ b/test cases/linuxlike/13 cmake dependency/setup_env.json
@@ -0,0 +1,3 @@
+{
+ "CMAKE_PREFIX_PATH": "@ROOT@/cmake_pref_env"
+}
diff --git a/test cases/linuxlike/13 cmake dependency/testFlagSet.c b/test cases/linuxlike/13 cmake dependency/testFlagSet.c
new file mode 100644
index 0000000..0c92690
--- /dev/null
+++ b/test cases/linuxlike/13 cmake dependency/testFlagSet.c
@@ -0,0 +1,18 @@
+#include<stdio.h>
+#include<zlib.h>
+
+#ifndef REQUIRED_MESON_FLAG1
+#error "REQUIRED_MESON_FLAG1 not set"
+#endif
+
+#ifndef REQUIRED_MESON_FLAG2
+#error "REQUIRED_MESON_FLAG2 not set"
+#endif
+
+int main(int argc, char *argv[]) {
+ printf("Hello World\n");
+ void * something = deflate;
+ if(something != 0)
+ return 0;
+ return 1;
+}
diff --git a/test cases/unit/55 introspection/meson.build b/test cases/unit/55 introspection/meson.build
index 3f013aa..7589f3f 100644
--- a/test cases/unit/55 introspection/meson.build
+++ b/test cases/unit/55 introspection/meson.build
@@ -25,7 +25,7 @@ var2 = 2.to_string()
var3 = 'test3'
t1 = executable('test' + var1, ['t1.cpp'], link_with: [sharedlib], install: true, build_by_default: get_option('test_opt2'))
-t2 = executable('test@0@'.format('@0@'.format(var2)), 't2.cpp', link_with: [staticlib])
+t2 = executable('test@0@'.format('@0@'.format(var2)), sources: ['t2.cpp'], link_with: [staticlib])
t3 = executable(var3, 't3.cpp', link_with: [sharedlib, staticlib], dependencies: [dep1])
### BEGIN: Test inspired by taisei: https://github.com/taisei-project/taisei/blob/master/meson.build#L293
diff --git a/test cases/windows/9 vs module defs generated/subdir/meson.build b/test cases/windows/9 vs module defs generated/subdir/meson.build
index 5d390a0..356f83a 100644
--- a/test cases/windows/9 vs module defs generated/subdir/meson.build
+++ b/test cases/windows/9 vs module defs generated/subdir/meson.build
@@ -7,3 +7,4 @@ def_file = configure_file(
)
shlib = shared_library('somedll', 'somedll.c', vs_module_defs : def_file)
+shmod = shared_module('somemod', 'somedll.c', vs_module_defs : def_file)