aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci_frameworks.yml25
-rw-r--r--.github/workflows/os_comp.yml27
-rw-r--r--.github/workflows/unusedargs_missingreturn.yml4
-rw-r--r--azure-pipelines.yml6
-rw-r--r--ci/azure-steps.yml2
-rw-r--r--cross/linux-mingw-w64-32bit.txt1
-rw-r--r--cross/ubuntu-armhf.txt1
-rw-r--r--data/syntax-highlighting/vim/ftdetect/meson.vim1
-rw-r--r--docs/markdown/Adding-new-projects-to-wrapdb.md6
-rw-r--r--docs/markdown/Cross-compilation.md5
-rw-r--r--docs/markdown/Reference-manual.md25
-rw-r--r--docs/markdown/Reference-tables.md54
-rw-r--r--docs/markdown/Release-procedure.md39
-rw-r--r--docs/markdown/Trial-conversions.md22
-rw-r--r--docs/markdown/Users.md35
-rw-r--r--docs/markdown/Videos.md6
-rw-r--r--docs/markdown/howtox.md34
-rw-r--r--docs/markdown/index.md8
-rw-r--r--docs/markdown/snippets/message_warning_concat.md4
-rw-r--r--docs/markdown/snippets/pkg_config_libdir.md3
-rw-r--r--docs/sitemap.txt1
-rw-r--r--mesonbuild/backend/backends.py17
-rw-r--r--mesonbuild/backend/vs2010backend.py4
-rw-r--r--mesonbuild/build.py8
-rw-r--r--mesonbuild/cmake/__init__.py3
-rw-r--r--mesonbuild/cmake/interpreter.py2
-rw-r--r--mesonbuild/compilers/compilers.py4
-rw-r--r--mesonbuild/coredata.py2
-rw-r--r--mesonbuild/dependencies/__init__.py4
-rw-r--r--mesonbuild/dependencies/base.py82
-rw-r--r--mesonbuild/dependencies/misc.py23
-rw-r--r--mesonbuild/dependencies/ui.py3
-rw-r--r--mesonbuild/envconfig.py19
-rw-r--r--mesonbuild/environment.py71
-rw-r--r--mesonbuild/interpreter.py38
-rw-r--r--mesonbuild/linkers.py22
-rw-r--r--mesonbuild/mdist.py10
-rw-r--r--mesonbuild/mesonlib.py14
-rw-r--r--mesonbuild/modules/pkgconfig.py7
-rwxr-xr-xmesonbuild/msubprojects.py30
-rw-r--r--mesonbuild/wrap/wrap.py95
-rwxr-xr-xrun_project_tests.py4
-rwxr-xr-xrun_tests.py38
-rwxr-xr-xrun_unittests.py156
-rw-r--r--test cases/cmake/5 object library/main.cpp1
-rw-r--r--test cases/cmake/6 object library no dep/main.cpp1
-rw-r--r--test cases/common/219 source set configuration_data/all.h6
-rw-r--r--test cases/common/219 source set configuration_data/f.c2
-rw-r--r--test cases/common/220 source set dictionary/all.h6
-rw-r--r--test cases/common/220 source set dictionary/f.c2
-rw-r--r--test cases/common/222 source set realistic example/meson.build2
-rwxr-xr-xtest cases/common/52 custom target/depfile/dep.py2
-rwxr-xr-xtest cases/common/53 custom target chain/my_compiler.py2
-rwxr-xr-xtest cases/common/53 custom target chain/my_compiler2.py2
-rwxr-xr-xtest cases/common/53 custom target chain/usetarget/subcomp.py2
-rw-r--r--test cases/common/68 build always/version.h2
-rw-r--r--test cases/common/69 vcstag/tagprog.c2
-rwxr-xr-xtest cases/common/99 manygen/subdir/manygen.py2
-rw-r--r--test cases/cuda/11 cuda dependency (nvcc)/version_reqs/prog.cu21
-rw-r--r--test cases/fortran/12 submodule/meson.build5
-rw-r--r--test cases/frameworks/1 boost/meson.build18
-rw-r--r--test cases/frameworks/31 curses/main.c7
-rw-r--r--test cases/frameworks/31 curses/meson.build9
-rw-r--r--test cases/frameworks/4 qt/meson.build19
-rw-r--r--test cases/frameworks/4 qt/meson_options.txt1
-rw-r--r--test cases/frameworks/4 qt/q5core.cpp2
-rw-r--r--test cases/frameworks/6 gettext/meson.build5
-rw-r--r--test cases/frameworks/7 gnome/meson.build5
-rw-r--r--test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake37
-rw-r--r--test cases/linuxlike/13 cmake dependency/meson.build2
-rwxr-xr-xtest cases/linuxlike/14 static dynamic linkage/verify_static.py2
-rw-r--r--test cases/linuxlike/15 ld binary/meson.build4
-rwxr-xr-xtest cases/unit/11 cross prog/some_cross_tool.py2
-rwxr-xr-xtest cases/unit/11 cross prog/sometool.py2
-rwxr-xr-xtest cases/unit/39 python extmodule/blaster.py2
-rwxr-xr-xtest cases/unit/61 identity cross/build_wrapper.py2
-rwxr-xr-xtest cases/unit/61 identity cross/host_wrapper.py2
-rw-r--r--test cases/unit/73 wrap file url/meson.build4
-rw-r--r--test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xzbin0 -> 228 bytes
-rw-r--r--test cases/unit/73 wrap file url/subprojects/foo.tar.xzbin0 -> 216 bytes
-rw-r--r--test cases/windows/16 gui app/gui_app_tester.py29
-rw-r--r--test cases/windows/16 gui app/meson.build9
-rw-r--r--test cases/windows/8 find program/test-script2
83 files changed, 816 insertions, 374 deletions
diff --git a/.github/workflows/ci_frameworks.yml b/.github/workflows/ci_frameworks.yml
index 682f5b9..12d41f8 100644
--- a/.github/workflows/ci_frameworks.yml
+++ b/.github/workflows/ci_frameworks.yml
@@ -59,3 +59,28 @@ jobs:
with:
name: HDF5_Mac_test
path: build/meson-logs/testlog.txt
+
+ Qt4macos:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v1
+ - uses: actions/setup-python@v1
+ with:
+ python-version: '3.x'
+ - run: python -m pip install -e .
+ - run: brew install pkg-config ninja gcc
+ - run: brew tap cartr/qt4
+ - run: brew install qt@4
+ - run: meson setup "test cases/frameworks/4 qt" build -Drequired=qt4
+ - run: ninja -C build
+ - uses: actions/upload-artifact@v1
+ if: failure()
+ with:
+ name: Qt4_Mac_build
+ path: build/meson-logs/meson-log.txt
+ - run: meson test -C build -v
+ - uses: actions/upload-artifact@v1
+ if: failure()
+ with:
+ name: Qt4_Mac_test
+ path: build/meson-logs/testlog.txt
diff --git a/.github/workflows/os_comp.yml b/.github/workflows/os_comp.yml
new file mode 100644
index 0000000..387b9c1
--- /dev/null
+++ b/.github/workflows/os_comp.yml
@@ -0,0 +1,27 @@
+name: OS Compatibility Tests
+
+on: [push, pull_request]
+
+jobs:
+ xenial:
+ name: Ubuntu 16.04 (xenial)
+ runs-on: ubuntu-16.04
+ steps:
+ - uses: actions/checkout@v1
+ - name: Install Dependencies
+ run: |
+ sudo apt update -yq
+ sudo apt install -yq --no-install-recommends python3-setuptools python3-pip g++ gfortran gobjc gobjc++ zlib1g-dev python-dev python3-dev libboost-all-dev
+ - name: Remove GitHub boost version
+ run: sudo rm -rf /usr/local/share/boost
+ - name: Install ninja-build tool
+ uses: seanmiddleditch/gha-setup-ninja@v1
+ - name: Python version
+ run: python3 --version
+ - name: Ninja version
+ run: ninja --version
+ - name: Run tests
+ run: python3 run_tests.py
+ env:
+ CI: '1'
+ XENIAL: '1'
diff --git a/.github/workflows/unusedargs_missingreturn.yml b/.github/workflows/unusedargs_missingreturn.yml
index c190af0..fa4405b 100644
--- a/.github/workflows/unusedargs_missingreturn.yml
+++ b/.github/workflows/unusedargs_missingreturn.yml
@@ -43,6 +43,7 @@ jobs:
sudo apt install -yq --no-install-recommends g++ gfortran ninja-build gobjc gobjc++
- run: python run_project_tests.py --only cmake common fortran platform-linux "objective c" "objective c++"
env:
+ CI: "1"
CFLAGS: "-Werror=unused-parameter -Werror=return-type -Werror=strict-prototypes"
CPPFLAGS: "-Werror=unused-parameter -Werror=return-type"
FFLAGS: "-fimplicit-none"
@@ -54,9 +55,10 @@ jobs:
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- - run: pip install ninja
+ - run: pip install ninja pefile
- run: python run_project_tests.py --only platform-windows
env:
+ CI: "1"
CFLAGS: "-Werror=unused-parameter -Werror=return-type -Werror=strict-prototypes"
CPPFLAGS: "-Werror=unused-parameter -Werror=return-type"
FFLAGS: "-fimplicit-none"
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index b7f2a77..cb44159 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -124,8 +124,8 @@ jobs:
displayName: Install Dependencies
- script: |
set PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32
- env.exe -- python3 -m pip --disable-pip-version-check install pytest-xdist
- displayName: pip install pytest-xdist
+ env.exe -- python3 -m pip --disable-pip-version-check install pefile pytest-xdist
+ displayName: pip install pefile pytest-xdist
- script: |
set BOOST_ROOT=
set PATH=%CYGWIN_ROOT%\bin;%SYSTEMROOT%\system32
@@ -188,7 +188,9 @@ jobs:
mingw-w64-$(MSYS2_ARCH)-python2 ^
mingw-w64-$(MSYS2_ARCH)-python3 ^
mingw-w64-$(MSYS2_ARCH)-python3-setuptools ^
+ mingw-w64-$(MSYS2_ARCH)-python3-pip ^
%TOOLCHAIN%
+ %MSYS2_ROOT%\usr\bin\bash -lc "python3 -m pip --disable-pip-version-check install pefile"
displayName: Install Dependencies
- powershell: |
# https://github.com/mesonbuild/meson/issues/5807
diff --git a/ci/azure-steps.yml b/ci/azure-steps.yml
index ff34c45..ef31208 100644
--- a/ci/azure-steps.yml
+++ b/ci/azure-steps.yml
@@ -152,7 +152,7 @@ steps:
python --version
# Needed for running unit tests in parallel.
- python -m pip --disable-pip-version-check install --upgrade pytest-xdist
+ python -m pip --disable-pip-version-check install --upgrade pefile pytest-xdist
echo ""
diff --git a/cross/linux-mingw-w64-32bit.txt b/cross/linux-mingw-w64-32bit.txt
index 8707a60..c2ea605 100644
--- a/cross/linux-mingw-w64-32bit.txt
+++ b/cross/linux-mingw-w64-32bit.txt
@@ -6,6 +6,7 @@ strip = '/usr/bin/i686-w64-mingw32-strip'
pkgconfig = '/usr/bin/i686-w64-mingw32-pkg-config'
windres = '/usr/bin/i686-w64-mingw32-windres'
exe_wrapper = 'wine'
+ld = '/usr/bin/i686-w64-mingw32-ld'
[properties]
# Directory that contains 'bin', 'lib', etc
diff --git a/cross/ubuntu-armhf.txt b/cross/ubuntu-armhf.txt
index a6e1f15..45a272a 100644
--- a/cross/ubuntu-armhf.txt
+++ b/cross/ubuntu-armhf.txt
@@ -7,6 +7,7 @@ rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/b
ar = '/usr/arm-linux-gnueabihf/bin/ar'
strip = '/usr/arm-linux-gnueabihf/bin/strip'
pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config'
+ld = '/usr/bin/arm-linux/gnueabihf-ld'
[properties]
root = '/usr/arm-linux-gnueabihf'
diff --git a/data/syntax-highlighting/vim/ftdetect/meson.vim b/data/syntax-highlighting/vim/ftdetect/meson.vim
index 84db70c..3233c58 100644
--- a/data/syntax-highlighting/vim/ftdetect/meson.vim
+++ b/data/syntax-highlighting/vim/ftdetect/meson.vim
@@ -1,2 +1,3 @@
au BufNewFile,BufRead meson.build set filetype=meson
au BufNewFile,BufRead meson_options.txt set filetype=meson
+au BufNewFile,BufRead *.wrap set filetype=dosini
diff --git a/docs/markdown/Adding-new-projects-to-wrapdb.md b/docs/markdown/Adding-new-projects-to-wrapdb.md
index c79cfd3..bbe945d 100644
--- a/docs/markdown/Adding-new-projects-to-wrapdb.md
+++ b/docs/markdown/Adding-new-projects-to-wrapdb.md
@@ -47,7 +47,7 @@ files - should be also provided.
### Request a new repository or branch
-Create an issue on the [wrapweb bug tracker](https://github.com/mesonbuild/wrapweb/issues)
+Create an issue on the [wrapdb bug tracker](https://github.com/mesonbuild/wrapdb/issues)
using *Title* and *Description* below as a template.
*Title:* `new wrap: <project_name>`
@@ -131,8 +131,8 @@ system has native support for Git subprojects.
## Creator script
-The WrapDB repository has a
-[helper script](https://github.com/mesonbuild/wrapweb/blob/master/mesonwrap.py)
+The WrapDB repository has a
+[helper script](https://github.com/mesonbuild/mesonwrap/blob/master/mesonwrap.py)
to generate new repositories, verify them and update them.
## Reviewing wraps
diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md
index b3cdc81..6894c0d 100644
--- a/docs/markdown/Cross-compilation.md
+++ b/docs/markdown/Cross-compilation.md
@@ -138,6 +138,7 @@ has_function_printf = true
c_args = ['-DCROSS=1', '-DSOMETHING=3']
c_link_args = ['-some_link_arg']
sys_root = '/some/path'
+pkg_config_libdir = '/some/path/lib/pkgconfig'
```
In most cases you don't need the size and alignment settings, Meson
@@ -155,6 +156,10 @@ internally by Meson to set the PKG_CONFIG_SYSROOT_DIR environment variable
for pkg-config. If this is unset the host system is assumed to share a root
with the build system.
+*Since 0.54.0* The pkg_config_libdir property may point to a list of path used
+internally by Meson to set the PKG_CONFIG_LIBDIR environment variable for pkg-config.
+This prevents pkg-config from searching cross dependencies in system directories.
+
One important thing to note, if you did not define an `exe_wrapper` in
the previous section, is that Meson will make a best-effort guess at
whether it can run the generated binaries on the build machine. It
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index c73e5a5..57fc1f7 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1198,6 +1198,9 @@ them for the default behaviour for each platform.
This function prints its argument to stdout.
+**Since 0.54.0** Can take more more than one argument that will be separated by
+space.
+
### warning()
``` meson
@@ -1208,6 +1211,9 @@ This function prints its argument to stdout prefixed with WARNING:.
*Added 0.44.0*
+**Since 0.54.0** Can take more more than one argument that will be separated by
+space.
+
### summary()
``` meson
@@ -1694,14 +1700,17 @@ The `meson` object allows you to introspect various properties of the
system. This object is always mapped in the `meson` variable. It has
the following methods.
-- `add_dist_script(script_name, arg1, arg, ...)` causes the script given as argument to run during
- `dist` operation after the distribution source has been generated
- but before it is archived. Note that this runs the script file that
- is in the _staging_ directory, not the one in the source
- directory. If the script file can not be found in the staging
- directory, it is a hard error. This command can only invoked from
- the main project, calling it from a subproject is a hard
- error. Available since 0.48.0. Before 0.49.0, the function only accepted a single argument.
+- `add_dist_script(script_name, arg1, arg, ...)` causes the script
+ given as argument to run during `dist` operation after the
+ distribution source has been generated but before it is
+ archived. Note that this runs the script file that is in the
+ _staging_ directory, not the one in the source directory. If the
+ script file can not be found in the staging directory, it is a hard
+ error. This command can only invoked from the main project, calling
+ it from a subproject is a hard error. Available since 0.48.0. Before
+ 0.49.0, the function only accepted a single argument. Since 0.54.0
+ the `MESON_SOURCE_ROOT` and `MESON_BUILD_ROOT` environment variables
+ are set when dist scripts are run.
- `add_install_script(script_name, arg1, arg2, ...)` causes the script
given as an argument to be run during the install step, this script
diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md
index 61f4803..86524b7 100644
--- a/docs/markdown/Reference-tables.md
+++ b/docs/markdown/Reference-tables.md
@@ -60,31 +60,33 @@ These are returned by the `cpu_family` method of `build_machine`,
`host_machine` and `target_machine`. For cross compilation they are
set in the cross file.
-| Value | Comment |
-| ----- | ------- |
-| aarch64 | 64 bit ARM processor |
-| alpha | DEC Alpha processor |
-| arc | 32 bit ARC processor |
-| arm | 32 bit ARM processor |
-| e2k | MCST Elbrus processor |
-| ia64 | Itanium processor |
-| microblaze | MicroBlaze processor |
-| mips | 32 bit MIPS processor |
-| mips64 | 64 bit MIPS processor |
-| parisc | HP PA-RISC processor |
-| ppc | 32 bit PPC processors |
-| ppc64 | 64 bit PPC processors |
-| riscv32 | 32 bit RISC-V Open ISA|
-| riscv64 | 64 bit RISC-V Open ISA|
-| rl78 | Renesas RL78 |
-| rx | Renesas RX 32 bit MCU |
-| s390x | IBM zSystem s390x |
-| sparc | 32 bit SPARC |
-| sparc64 | SPARC v9 processor |
-| wasm32 | 32 bit Webassembly |
-| wasm64 | 64 bit Webassembly |
-| x86 | 32 bit x86 processor |
-| x86_64 | 64 bit x86 processor |
+| Value | Comment |
+| ----- | ------- |
+| aarch64 | 64 bit ARM processor |
+| alpha | DEC Alpha processor |
+| arc | 32 bit ARC processor |
+| arm | 32 bit ARM processor |
+| e2k | MCST Elbrus processor |
+| ia64 | Itanium processor |
+| m68k | Motorola 68000 processor |
+| microblaze | MicroBlaze processor |
+| mips | 32 bit MIPS processor |
+| mips64 | 64 bit MIPS processor |
+| parisc | HP PA-RISC processor |
+| ppc | 32 bit PPC processors |
+| ppc64 | 64 bit PPC processors |
+| riscv32 | 32 bit RISC-V Open ISA |
+| riscv64 | 64 bit RISC-V Open ISA |
+| rl78 | Renesas RL78 |
+| rx | Renesas RX 32 bit MCU |
+| s390 | IBM zSystem s390 |
+| s390x | IBM zSystem s390x |
+| sparc | 32 bit SPARC |
+| sparc64 | SPARC v9 processor |
+| wasm32 | 32 bit Webassembly |
+| wasm64 | 64 bit Webassembly |
+| x86 | 32 bit x86 processor |
+| x86_64 | 64 bit x86 processor |
Any cpu family not listed in the above list is not guaranteed to
remain stable in future releases.
@@ -141,7 +143,7 @@ linker flags.
It is recommended that you **do not use these**. They are provided purely to
for backwards compatibility with other build systems. There are many caveats to
their use, especially when rebuilding the project. It is **highly** recommended
-that you use [the command line arguments](#language-arguments-parameters-names)
+that you use [the command line arguments](#language-arguments-parameter-names)
instead.
| Name | Comment |
diff --git a/docs/markdown/Release-procedure.md b/docs/markdown/Release-procedure.md
index 9168ed8..caf4973 100644
--- a/docs/markdown/Release-procedure.md
+++ b/docs/markdown/Release-procedure.md
@@ -4,23 +4,42 @@
# Trunk
-Meson operates under the principle that trunk should (in theory) be always good enough for release. That is, all code merged in trunk must pass all unit tests. Any broken code should either be fixed or reverted immediately.
+Meson operates under the principle that trunk should (in theory) be always
+good enough for release. That is, all code merged in trunk must pass all unit
+tests. Any broken code should either be fixed or reverted immediately.
-People who are willing to tolerate the occasional glitch should be able to use Meson trunk for their day to day development if they so choose.
+People who are willing to tolerate the occasional glitch should be able to
+use Meson trunk for their day to day development if they so choose.
# Major releases
-Major releases are currently in the form 0.X.0, where X is an increasing number. We aim to do a major release roughly once a month, though the schedule is not set in stone. Prior to the release there is a stabilisation period of roughly a week. Major changes should not be committed during this time, but instead only small scale fixes.
+Major releases are currently in the form 0.X.0, where X is an increasing
+number. We aim to do a major release roughly once a month, though the
+schedule is not set in stone.
+
+Before a major release is made a stable branch will be made, and 0.X.0-rc1
+release candidate will be made. A new milestone for 0.X.0 will be made, and
+all bugs effecting the RC will be assigned to this milestone. Patches fixing
+bugs in the milestone will be picked to the stable branch, and normal
+development will continue on the master branch. Every week after after this a
+new release candidate will be made until all bugs are resolved in that
+milestone. When all of the bugs are fixed the 0.X.0 release will be made.
# Bugfix releases
-Bugfix releases contain only minor fixes to major releases and are designated by incrementing the last digit of the version number. The criteria for a bug fix release is one of the following:
+Bugfix releases contain only minor fixes to major releases and are designated
+by incrementing the last digit of the version number. The criteria for a bug
+fix release is one of the following:
- - release has a major regression compared to the previous release (making existing projects unbuildable)
+ - release has a major regression compared to the previous release (making
+ existing projects unbuildable)
- the release has a serious bug causing data loss or equivalent
- other unforeseen major issue
-In these cases a bug fix release can be made. It shall contain _only_ the fix for the issue (or issues) in question and other minor bug fixes. Only changes that have already landed in trunk will be considered for inclusion. No new functionality shall be added.
+In these cases a bug fix release can be made. It shall contain _only_ the fix
+for the issue (or issues) in question and other minor bug fixes. Only changes
+that have already landed in trunk will be considered for inclusion. No new
+functionality shall be added.
# Requesting a bug fix release
@@ -28,7 +47,8 @@ The process for requesting that a bug fix release be made goes roughly as follow
- file a bug about the core issue
- file a patch fixing it if possible
- - contact the development team and request a bug fix release (IRC is the preferred contact medium)
+ - contact the development team and request a bug fix release (IRC is the
+ preferred contact medium)
The request should contain the following information:
@@ -38,4 +58,7 @@ The request should contain the following information:
There is no need to write a long and complicated request report. Something like the following is sufficient:
-> The latest release has a regression where trying to do Foo using Bar breaks. This breaks all projects that use both, which includes at least [list of affected projects]. This causes problems for X amount of people and because of this we should do a bugfix release.
+> The latest release has a regression where trying to do Foo using Bar
+breaks. This breaks all projects that use both, which includes at least [list
+of affected projects]. This causes problems for X amount of people and
+because of this we should do a bugfix release.
diff --git a/docs/markdown/Trial-conversions.md b/docs/markdown/Trial-conversions.md
deleted file mode 100644
index 4d89b9a..0000000
--- a/docs/markdown/Trial-conversions.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: Trial conversions
-...
-
-# Trial conversions of existing projects
-
-To verify Meson's suitability for different types of projects, its developers do experimental build system conversions. In all simplicity it means that random projects are chosen and their build system is rewritten in Meson. Usually these are not fully polished ports, but should contain most of the work necessary to use Meson as the new build system.
-
-Here is a list of projects that have had a build system port done.
-
-* [Python 3](https://mail.python.org/pipermail/python-dev/2013-June/126748.html)
-* [Glib](https://mail.gnome.org/archives/gtk-devel-list/2013-August/msg00001.html)
-* [QtCreator](http://lists.qt-project.org/pipermail/qt-creator/2014-May/003584.html), and a [followup](http://lists.qt-project.org/pipermail/qt-creator/2014-May/003598.html) on unity builds
-* [SDL 2](https://forums.libsdl.org/viewtopic.php?t=10093&sid=8cf1d6c83d4d73fe6cfbb7cbb16b3d28)
-* [Mesa3D](https://lists.freedesktop.org/archives/mesa-dev/2014-July/064160.html)
-* [Mame](http://www.mameworld.info/ubbthreads/showthreaded.php?Cat=&Number=332119&page=0&view=expanded&sb=5&o=&fpart=1&vc=1)
-* [Firefox NSPR](https://groups.google.com/forum/#!topic/mozilla.dev.builds/daS3DK2F1MQ)
-* [Wayland](https://lists.freedesktop.org/archives/wayland-devel/2015-February/020124.html)
-
-## More from WrapDB
-
-The [Meson Wrap database](https://wrapdb.mesonbuild.com) contains several projects that have been converted into Meson and are ready to use.
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index 7290a5b..32962dd 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -4,8 +4,13 @@ title: Users
# List of projects using Meson
-If you have a project that uses Meson that you want to add to this list, please [file a pull-request](https://github.com/mesonbuild/meson/edit/master/docs/markdown/Users.md) for it. All the software on this list is tested for regressions before release, so it's highly recommended that projects add themselves here. Some additional projects are
-listed in the [`meson` GitHub topic](https://github.com/topics/meson).
+If you have a project that uses Meson that you want to add to this
+list, please [file a
+pull-request](https://github.com/mesonbuild/meson/edit/master/docs/markdown/Users.md)
+for it. All the software on this list is tested for regressions before
+release, so it's highly recommended that projects add themselves
+here. Some additional projects are 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
@@ -22,7 +27,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [dbus-broker](https://github.com/bus1/dbus-broker), Linux D-Bus Message Broker
- [DPDK](http://dpdk.org/browse/dpdk), Data Plane Development Kit, a set of libraries and drivers for fast packet processing
- [DXVK](https://github.com/doitsujin/dxvk), a Vulkan-based Direct3D 11 implementation for Linux using Wine
- - [elementary OS](https://github.com/elementary/), Linux desktop oriented distribution
+ - [elementary OS](https://github.com/elementary/), Linux desktop oriented distribution
- [Emeus](https://github.com/ebassi/emeus), constraint based layout manager for GTK+
- [ESP8266 Arduino sample project](https://github.com/trilader/arduino-esp8266-meson), sample project for using the ESP8266 Arduino port with Meson
- [FeedReader](https://github.com/jangernert/FeedReader), a modern desktop application designed to complement existing web-based RSS accounts
@@ -31,7 +36,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [fwupd](https://github.com/hughsie/fwupd), a simple daemon to allow session software to update firmware
- [GameMode](https://github.com/FeralInteractive/gamemode), a daemon/lib combo for Linux that allows games to request a set of optimisations be temporarily applied to the host OS
- [Geary](https://wiki.gnome.org/Apps/Geary), an email application built around conversations, for the GNOME 3 desktop.
- - [GLib](https://gitlab.gnome.org/GNOME/glib), cross-platform C library used by GTK+ and GStreamer (not the default yet)
+ - [GLib](https://gitlab.gnome.org/GNOME/glib), cross-platform C library used by GTK+ and GStreamer
- [GNOME Boxes](https://gitlab.gnome.org/GNOME/gnome-boxes), a GNOME hypervisor
- [GNOME Builder](https://gitlab.gnome.org/GNOME/gnome-builder), an IDE for the GNOME platform
- [GNOME MPV](https://github.com/gnome-mpv/gnome-mpv), GNOME frontend to the mpv video player
@@ -42,7 +47,7 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [GNU FriBidi](https://github.com/fribidi/fribidi), the open source implementation of the Unicode Bidirectional Algorithm
- [Graphene](https://ebassi.github.io/graphene/), a thin type library for graphics
- [Grilo](https://git.gnome.org/browse/grilo) and [Grilo plugins](https://git.gnome.org/browse/grilo-plugins), the Grilo multimedia framework
- - [GStreamer](https://cgit.freedesktop.org/gstreamer/gstreamer/), multimedia framework (not the default yet)
+ - [GStreamer](https://cgit.freedesktop.org/gstreamer/gstreamer/), multimedia framework
- [GTK+](https://gitlab.gnome.org/GNOME/gtk), the multi-platform toolkit used by GNOME
- [GtkDApp](https://gitlab.com/csoriano/GtkDApp), an application template for developing Flatpak apps with Gtk+ and D
- [GVfs](https://git.gnome.org/browse/gvfs/), a userspace virtual filesystem designed to work with the I/O abstraction of GIO
@@ -68,9 +73,9 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [libglvnd](https://gitlab.freedesktop.org/glvnd/libglvnd), Vendor neutral OpenGL dispatch library for Unix-like OSes
- [Libhttpseverywhere](https://git.gnome.org/browse/libhttpseverywhere), a library to enable httpseverywhere on any desktop app
- [libmodulemd](https://github.com/fedora-modularity/libmodulemd), a GObject Introspected library for managing [Fedora Project](https://getfedora.org/) module metadata.
- - [Libosmscout](https://github.com/Framstag/libosmscout), a C++ library for offline map rendering, routing and location
+ - [Libosmscout](https://github.com/Framstag/libosmscout), a C++ library for offline map rendering, routing and location
lookup based on OpenStreetMap data
- - [libspng](https://gitlab.com/randy408/libspng), a C library for reading and writing Portable Network Graphics (PNG)
+ - [libspng](https://gitlab.com/randy408/libspng), a C library for reading and writing Portable Network Graphics (PNG)
format files
- [libui](https://github.com/andlabs/libui), a simple and portable (but not inflexible) GUI library in C that uses the native GUI technologies of each platform it supports
- [Libva](https://github.com/intel/libva), an implementation for the VA (VIdeo Acceleration) API
@@ -81,22 +86,23 @@ format files
- [mrsh](https://github.com/emersion/mrsh), a minimal POSIX shell
- [Nautilus](https://gitlab.gnome.org/GNOME/nautilus), the GNOME file manager
- [Nemo](https://github.com/linuxmint/nemo), the file manager for the Cinnamon desktop environment
- - [oomd](https://github.com/facebookincubator/oomd), a userspace Out-Of-Memory (OOM) killer for Linux systems
+ - [oomd](https://github.com/facebookincubator/oomd), a userspace Out-Of-Memory (OOM) killer for Linux systems
- [OpenH264](https://github.com/cisco/openh264), open source H.264 codec
- [OpenHMD](https://github.com/OpenHMD/OpenHMD), a free and open source API and drivers for immersive technology, such as head mounted displays with built in head tracking
- - [Orc](http://cgit.freedesktop.org/gstreamer/orc/), the Optimized Inner Loop Runtime Compiler (not the default yet)
+ - [Orc](http://cgit.freedesktop.org/gstreamer/orc/), the Optimized Inner Loop Runtime Compiler
- [OTS](https://github.com/khaledhosny/ots), the OpenType Sanitizer, parses and serializes OpenType files (OTF, TTF) and WOFF and WOFF2 font files, validating and sanitizing them as it goes. Used by Chromium and Firefox
- [Outlier](https://github.com/kerolasa/outlier), a small Hello World style meson example project
- [Pacman](https://git.archlinux.org/pacman.git/tree/), a package manager for Arch Linux
- - [Pango](https://git.gnome.org/browse/pango/), an Internationalized text layout and rendering library (not the default yet)
+ - [Pango](https://git.gnome.org/browse/pango/), an Internationalized text layout and rendering library
- [Parzip](https://github.com/jpakkane/parzip), a multithreaded reimplementation of Zip
- [Peek](https://github.com/phw/peek), simple animated GIF screen recorder with an easy to use interface
- - [PicoLibc](https://github.com/keith-packard/picolibc), a standard C library for small embedded systems with limited RAM
+ - [PicoLibc](https://github.com/keith-packard/picolibc), a standard C library for small embedded systems with limited RAM
- [PipeWire](https://github.com/PipeWire/pipewire), a framework for video and audio for containerized applications
- [Pithos](https://github.com/pithos/pithos), a Pandora Radio client
- [Pitivi](https://github.com/pitivi/pitivi/), a nonlinear video editor
- [Playerctl](https://github.com/acrisci/playerctl), mpris command-line controller and library for spotify, vlc, audacious, bmp, cmus, and others
- [Polari](https://gitlab.gnome.org/GNOME/polari), an IRC client
+ - [qboot](https://github.com/bonzini/qboot), a minimal x86 firmware for booting Linux kernels
- [radare2](https://github.com/radare/radare2), unix-like reverse engineering framework and commandline tools (not the default)
- [RxDock](https://gitlab.com/rxdock/rxdock), a protein-ligand docking software designed for high throughput virtual screening (fork of rDock)
- [SSHFS](https://github.com/libfuse/sshfs), allows you to mount a remote filesystem using SFTP
@@ -108,13 +114,16 @@ format files
- [Terminology](https://github.com/billiob/terminology), a terminal emulator based on the Enlightenment Foundation Libraries
- [Tilix](https://github.com/gnunn1/tilix), a tiling terminal emulator for Linux using GTK+ 3
- [Valum](https://github.com/valum-framework/valum), a micro web framework written in Vala
- - [Wayland and Weston](https://lists.freedesktop.org/archives/wayland-devel/2016-November/031984.html), a next generation display server (not merged yet)
+ - [Wayland](https://github.com/wayland-project/wayland) and [Weston](https://github.com/wayland-project/weston), a next generation display server
- [wlroots](https://github.com/swaywm/wlroots), a modular Wayland compositor library
- [wxFormBuilder](https://github.com/wxFormBuilder/wxFormBuilder), RAD tool for wxWidgets GUI design
- [xi-gtk](https://github.com/eyelash/xi-gtk), a GTK+ front-end for the Xi editor
- [Xorg](https://cgit.freedesktop.org/xorg/xserver/), the X.org display server (not the default yet)
- [zathura](https://github.com/pwmt/zathura), a highly customizable and functional document viewer based on the
girara user interface library and several document libraries
+ - [Zrythm](https://git.zrythm.org/cgit/zrythm), a cross-platform digital audio workstation using GTK+ 3
- [ZStandard](https://github.com/facebook/zstd/commit/4dca56ed832c6a88108a2484a8f8ff63d8d76d91), a compression algorithm developed at Facebook (not used by default)
-Note that a more up-to-date list of GNOME projects that use Meson can be found [here](https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting).
+Note that a more up-to-date list of GNOME projects that use Meson can
+be found
+[here](https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting).
diff --git a/docs/markdown/Videos.md b/docs/markdown/Videos.md
index f2e37a7..fb60038 100644
--- a/docs/markdown/Videos.md
+++ b/docs/markdown/Videos.md
@@ -4,8 +4,12 @@ short-description: Videos about Meson
# Videos
+ - [Behind (and under) the scenes of the Meson build
+ system](https://www.youtube.com/watch?v=iLN6wL7ExHU), Linux.conf.au
+ 2020
+
- [Behind the Scenes of a C++ Build
- System](https://www.youtube.com/watch?v=34KzT2yvQuM) CppCon 2019
+ System](https://www.youtube.com/watch?v=34KzT2yvQuM), CppCon 2019
- [Compiling Multi-Million Line C++ Code Bases Effortlessly with the
Meson Build system](https://www.youtube.com/watch?v=SCZLnopmYBM),
diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md
index f73d6b9..5deaa7e 100644
--- a/docs/markdown/howtox.md
+++ b/docs/markdown/howtox.md
@@ -28,24 +28,36 @@ native-files and the latter via the cross file only.
## Set dynamic linker
+Like the compiler, the linker is selected via the <compiler variable>_LD
+environment variable, or through the `<compiler entry>ld` entry in a native
+or cross file. You must be aware of whether you're using a compiler that
+invokes the linker itself (most compilers including GCC and Clang) or a
+linker that is invoked directly (when using MSVC or compilers that act like
+it, including Clang-Cl). With the former `cld` or `CC_LD` should be the value
+to pass to the compiler's special argument (such as `-fuse-ld` with clang and
+gcc), with the latter it should be an executable, such as `lld-link.exe`.
+
+*NOTE* In meson 0.53.0 the `ld` entry in the cross/native file and the `LD`
+environment variable was used, this resulted in a large number of regressions
+and was changed.
+
```console
-$ CC=clang LD=lld meson <options>
+$ CC=clang CC_LD=lld meson <options>
```
or
```console
-$ CC=clang-cl LD=link meson <options>
+$ CC=clang-cl CC_LD=link meson <options>
```
-Like the compiler, the linker is selected via the LD environment variable, or
-through the `ld` entry in a native or cross file. You must be aware of
-whehter you're using a compiler that invokes the linker itself (most
-compilers including GCC and Clang) or a linker that is invoked directly (when
-using MSVC or compilers that act like it, including Clang-Cl). With the
-former `ld` or `LD` should be the value to pass to the compiler's special
-argument (such as `-fuse-ld` with clang and gcc), with the latter it should
-be an exectuable, such as `lld-link.exe`.
+or in a cross or native file:
+
+```ini
+[binaries]
+c = 'clang'
+c_ld = 'lld'
+```
## Set default C/C++ language version
@@ -139,7 +151,7 @@ $ ninja coverage-html (or coverage-xml)
The coverage report can be found in the meson-logs subdirectory.
-Note: Currently, Meson does not support generating coverage reports
+Note: Currently, Meson does not support generating coverage reports
with Clang.
## Add some optimization to debug builds
diff --git a/docs/markdown/index.md b/docs/markdown/index.md
index e57cd69..ccd341f 100644
--- a/docs/markdown/index.md
+++ b/docs/markdown/index.md
@@ -24,6 +24,12 @@ code.
* built-in multiplatform dependency provider that works together with distro packages
* fun!
+## A full manual
+
+The documentation on this site is freely available for all. However
+there is also a full separate manual available for purchase [on this
+web page](https://meson-manual.com/).
+
## Community
There are two main methods of connecting with other Meson
@@ -37,7 +43,7 @@ The second way is via IRC. The channel to use is `#mesonbuild` at
Many projects out there are using Meson and their communities are also
a great resource for learning about what (and what not too!) do when
-trying to convert to using Meson.
+trying to convert to using Meson.
[A short list of Meson users can be found here](Users.md)
but there are many more. We would love to hear about your success
diff --git a/docs/markdown/snippets/message_warning_concat.md b/docs/markdown/snippets/message_warning_concat.md
new file mode 100644
index 0000000..39e9e6d
--- /dev/null
+++ b/docs/markdown/snippets/message_warning_concat.md
@@ -0,0 +1,4 @@
+## More than one argument to `message()` and `warning()`
+
+Arguments passed to `message()` and `warning()` will be printed separated by
+space.
diff --git a/docs/markdown/snippets/pkg_config_libdir.md b/docs/markdown/snippets/pkg_config_libdir.md
new file mode 100644
index 0000000..691f8c5
--- /dev/null
+++ b/docs/markdown/snippets/pkg_config_libdir.md
@@ -0,0 +1,3 @@
+## Added 'pkg_config_libdir' property
+Allows to define a list of folders used by pkg-config for a cross build
+and avoid a system directories use.
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index 5850cc3..157574d 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -108,7 +108,6 @@ index.md
Pkg-config-files.md
Playground.md
Porting-from-autotools.md
- Trial-conversions.md
Use-of-Python.md
Users.md
Using-multiple-build-directories.md
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 2a07058..d75b7a4 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -793,8 +793,25 @@ class Backend:
fname = os.path.join(self.environment.get_source_dir(), sp, 'meson_options.txt')
if os.path.isfile(fname):
deps.append(os.path.join(self.build_to_src, sp, 'meson_options.txt'))
+ self.check_clock_skew(deps)
return deps
+ def check_clock_skew(self, file_list):
+ # If a file that leads to reconfiguration has a time
+ # stamp in the future, it will trigger an eternal reconfigure
+ # loop.
+ import time
+ now = time.time()
+ for f in file_list:
+ absf = os.path.join(self.environment.get_build_dir(), f)
+ ftime = os.path.getmtime(absf)
+ delta = ftime - now
+ # On Windows disk time stamps sometimes point
+ # to the future by a minuscule amount, less than
+ # 0.001 seconds. I don't know why.
+ if delta > 0.001:
+ raise MesonException('Clock skew detected. File {} has a time stamp {:.4f}s in the future.'.format(absf, delta))
+
def exe_object_to_cmd_array(self, exe):
if isinstance(exe, build.BuildTarget):
if exe.for_machine is not MachineChoice.BUILD:
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 9a84055..6d83ff9 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -1191,6 +1191,10 @@ class Vs2010Backend(backends.Backend):
targetmachine.text = 'MachineARM'
else:
raise MesonException('Unsupported Visual Studio target machine: ' + targetplatform)
+ # /nologo
+ ET.SubElement(link, 'SuppressStartupBanner').text = 'true'
+ # /release
+ ET.SubElement(link, 'SetChecksum').text = 'true'
meson_file_group = ET.SubElement(root, 'ItemGroup')
ET.SubElement(meson_file_group, 'None', Include=os.path.join(proj_to_src_dir, build_filename))
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 12274a6..1db930e 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -355,22 +355,22 @@ a hard error in the future.''' % name)
if not hasattr(self, 'typename'):
raise RuntimeError('Target type is not set for target class "{}". This is a bug'.format(type(self).__name__))
- def __lt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
+ def __lt__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]:
if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented
return self.get_id() < other.get_id()
- def __le__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
+ def __le__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]:
if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented
return self.get_id() <= other.get_id()
- def __gt__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
+ def __gt__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]:
if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented
return self.get_id() > other.get_id()
- def __ge__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
+ def __ge__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]:
if not hasattr(other, 'get_id') and not callable(other.get_id):
return NotImplemented
return self.get_id() >= other.get_id()
diff --git a/mesonbuild/cmake/__init__.py b/mesonbuild/cmake/__init__.py
index 5520ae3..01cc3f9 100644
--- a/mesonbuild/cmake/__init__.py
+++ b/mesonbuild/cmake/__init__.py
@@ -25,6 +25,7 @@ __all__ = [
'CMakeTraceLine',
'CMakeTraceParser',
'parse_generator_expressions',
+ 'language_map',
]
from .common import CMakeException
@@ -32,5 +33,5 @@ from .client import CMakeClient
from .executor import CMakeExecutor
from .fileapi import CMakeFileAPI
from .generator import parse_generator_expressions
-from .interpreter import CMakeInterpreter
+from .interpreter import CMakeInterpreter, language_map
from .traceparser import CMakeTarget, CMakeTraceLine, CMakeTraceParser
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 9155d6d..703815e 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -79,6 +79,8 @@ language_map = {
'c': 'C',
'cpp': 'CXX',
'cuda': 'CUDA',
+ 'objc': 'OBJC',
+ 'objcpp': 'OBJCXX',
'cs': 'CSharp',
'java': 'Java',
'fortran': 'Fortran',
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 5e8e18f..e8e72cf 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -386,7 +386,7 @@ class RunResult:
self.stdout = stdout
self.stderr = stderr
-class CompilerArgs(T.MutableSequence[str]):
+class CompilerArgs(collections.abc.MutableSequence):
'''
List-like class that manages a list of compiler arguments. Should be used
while constructing compiler arguments from various sources. Can be
@@ -655,7 +655,7 @@ class CompilerArgs(T.MutableSequence[str]):
new += self
return new
- def __eq__(self, other: T.Any) -> T.Union[bool, 'NotImplemented']:
+ def __eq__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]:
# Only allow equality checks against other CompilerArgs and lists instances
if isinstance(other, CompilerArgs):
return self.compiler == other.compiler and self.__container == other.__container
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index e80c524..2b7be7b 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -685,6 +685,8 @@ class CoreData:
unknown_options = ', '.join(sorted(unknown_options))
sub = 'In subproject {}: '.format(subproject) if subproject else ''
mlog.warning('{}Unknown options: "{}"'.format(sub, unknown_options))
+ mlog.log('The value of new options can be set with:')
+ mlog.log(mlog.bold('meson setup <builddir> --reconfigure -Dnew_option=new_value ...'))
if not self.is_cross_build():
self.copy_build_options_from_regular_ones()
diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py
index 889a610..cc8817d 100644
--- a/mesonbuild/dependencies/__init__.py
+++ b/mesonbuild/dependencies/__init__.py
@@ -23,7 +23,8 @@ from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDepen
from .coarrays import CoarrayDependency
from .mpi import MPIDependency
from .scalapack import ScalapackDependency
-from .misc import (BlocksDependency, NetCDFDependency, OpenMPDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency, LibGCryptDependency, GpgmeDependency, ShadercDependency)
+from .misc import (BlocksDependency, CursesDependency, NetCDFDependency, OpenMPDependency, Python3Dependency, ThreadDependency,
+ PcapDependency, CupsDependency, LibWmfDependency, LibGCryptDependency, GpgmeDependency, ShadercDependency)
from .platform import AppleFrameworks
from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency
@@ -46,6 +47,7 @@ packages.update({
# From misc:
'blocks': BlocksDependency,
+ 'curses': CursesDependency,
'netcdf': NetCDFDependency,
'openmp': OpenMPDependency,
'python3': Python3Dependency,
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 1890961..e9cf9ac 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -711,6 +711,12 @@ class PkgConfigDependency(ExternalDependency):
mlog.debug('PKG_CONFIG_PATH: ' + new_pkg_config_path)
env['PKG_CONFIG_PATH'] = new_pkg_config_path
+ pkg_config_libdir_prop = self.env.properties[self.for_machine].get_pkg_config_libdir()
+ if pkg_config_libdir_prop:
+ new_pkg_config_libdir = ':'.join([p for p in pkg_config_libdir_prop])
+ env['PKG_CONFIG_LIBDIR'] = new_pkg_config_libdir
+ mlog.debug('PKG_CONFIG_LIBDIR: ' + new_pkg_config_libdir)
+
fenv = frozenset(env.items())
targs = tuple(args)
cache = PkgConfigDependency.pkgbin_cache
@@ -1070,21 +1076,26 @@ class CMakeDependency(ExternalDependency):
return module
def __init__(self, name: str, environment: Environment, kwargs, language: str = None):
+ # Gather a list of all languages to support
+ self.language_list = [] # type: T.List[str]
if language is None:
+ compilers = None
if kwargs.get('native', False):
- if 'c' in environment.coredata.compilers.build.keys():
- language = 'c'
- elif 'cpp' in environment.coredata.compilers.build.keys():
- language = 'cpp'
- elif 'fortran' in environment.coredata.compilers.build.keys():
- language = 'fortran'
+ compilers = environment.coredata.compilers.build
else:
- if 'c' in environment.coredata.compilers.host.keys():
- language = 'c'
- elif 'cpp' in environment.coredata.compilers.host.keys():
- language = 'cpp'
- elif 'fortran' in environment.coredata.compilers.host.keys():
- language = 'fortran'
+ compilers = environment.coredata.compilers.host
+
+ candidates = ['c', 'cpp', 'fortran', 'objc', 'objcxx']
+ self.language_list += [x for x in candidates if x in compilers]
+ else:
+ self.language_list += [language]
+
+ # Add additional languages if required
+ if 'fortran' in self.language_list:
+ self.language_list += ['c']
+
+ # Ensure that the list is unique
+ self.language_list = list(set(self.language_list))
super().__init__('cmake', environment, language, kwargs)
self.name = name
@@ -1519,29 +1530,19 @@ class CMakeDependency(ExternalDependency):
# To make this general to
# any other language that might need this, we use a list for all
# languages and expand in the cmake Project(... LANGUAGES ...) statement.
- if self.language is None:
- cmake_language = ['NONE']
- elif self.language == 'c':
- cmake_language = ['C']
- elif self.language == 'cpp':
- cmake_language = ['CXX']
- elif self.language == 'cs':
- cmake_language = ['CSharp']
- elif self.language == 'cuda':
- cmake_language = ['CUDA']
- elif self.language == 'fortran':
- cmake_language = ['C', 'Fortran']
- elif self.language == 'objc':
- cmake_language = ['OBJC']
- elif self.language == 'objcpp':
- cmake_language = ['OBJCXX']
+ from ..cmake import language_map
+ cmake_language = [language_map[x] for x in self.language_list if x in language_map]
+ if not cmake_language:
+ cmake_language += ['NONE']
cmake_txt = """
cmake_minimum_required(VERSION ${{CMAKE_VERSION}})
project(MesonTemp LANGUAGES {})
""".format(' '.join(cmake_language)) + cmake_txt
- (build_dir / 'CMakeLists.txt').write_text(cmake_txt)
+ cm_file = build_dir / 'CMakeLists.txt'
+ cm_file.write_text(cmake_txt)
+ mlog.cmd_ci_include(cm_file.absolute().as_posix())
return str(build_dir)
@@ -1831,6 +1832,22 @@ class ExternalProgram:
return cls.from_entry(name, command)
@staticmethod
+ @functools.lru_cache(maxsize=None)
+ def _windows_sanitize_path(path: str) -> str:
+ # Ensure that we use USERPROFILE even when inside MSYS, MSYS2, Cygwin, etc.
+ if 'USERPROFILE' not in os.environ:
+ return path
+ # Ignore executables in the WindowsApps directory which are
+ # zero-sized wrappers that magically open the Windows Store to
+ # install the application.
+ appstore_dir = Path(os.environ['USERPROFILE']) / 'AppData' / 'Local' / 'Microsoft' / 'WindowsApps'
+ paths = []
+ for each in path.split(os.pathsep):
+ if Path(each) != appstore_dir:
+ paths.append(each)
+ return os.pathsep.join(paths)
+
+ @staticmethod
def from_entry(name, command):
if isinstance(command, list):
if len(command) == 1:
@@ -1955,7 +1972,7 @@ class ExternalProgram:
# On Windows, interpreted scripts must have an extension otherwise they
# cannot be found by a standard PATH search. So we do a custom search
# where we manually search for a script with a shebang in PATH.
- search_dirs = os.environ.get('PATH', '').split(';')
+ search_dirs = self._windows_sanitize_path(os.environ.get('PATH', '')).split(';')
for search_dir in search_dirs:
commands = self._search_dir(name, search_dir)
if commands:
@@ -1971,7 +1988,10 @@ class ExternalProgram:
if commands:
return commands
# Do a standard search in PATH
- command = shutil.which(name)
+ path = os.environ.get('PATH', None)
+ if mesonlib.is_windows() and path:
+ path = self._windows_sanitize_path(path)
+ command = shutil.which(name, path=path)
if mesonlib.is_windows():
return self._search_windows_special_cases(name, command)
# On UNIX-like platforms, shutil.which() is enough to find
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 88f64e0..9077222 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -557,3 +557,26 @@ class ShadercDependency(ExternalDependency):
@staticmethod
def get_methods():
return [DependencyMethods.SYSTEM, DependencyMethods.PKGCONFIG]
+
+class CursesDependency(ExternalDependency):
+ def __init__(self, environment, kwargs):
+ super().__init__('curses', environment, None, kwargs)
+ self.name = 'curses'
+ self.is_found = False
+ methods = listify(self.methods)
+
+ if set([DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]).intersection(methods):
+ pkgconfig_files = ['ncurses', 'ncursesw']
+ for pkg in pkgconfig_files:
+ pkgdep = PkgConfigDependency(pkg, environment, kwargs)
+ if pkgdep.found():
+ self.compile_args = pkgdep.get_compile_args()
+ self.link_args = pkgdep.get_link_args()
+ self.version = pkgdep.get_version()
+ self.is_found = True
+ self.pcdep = pkgdep
+ return
+
+ @staticmethod
+ def get_methods():
+ return [DependencyMethods.AUTO, DependencyMethods.PKGCONFIG]
diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py
index bdcc4a7..da411ef 100644
--- a/mesonbuild/dependencies/ui.py
+++ b/mesonbuild/dependencies/ui.py
@@ -373,7 +373,8 @@ class QtBaseDependency(ExternalDependency):
(k, v) = tuple(line.split(':', 1))
qvars[k] = v
# Qt on macOS uses a framework, but Qt for iOS/tvOS does not
- if self.env.machines.host.is_darwin() and 'ios' not in qvars['QMAKE_XSPEC'] and 'tvos' not in qvars['QMAKE_XSPEC']:
+ xspec = qvars.get('QMAKE_XSPEC', '')
+ if self.env.machines.host.is_darwin() and not any(s in xspec for s in ['ios', 'tvos']):
mlog.debug("Building for macOS, looking for framework")
self._framework_detect(qvars, mods, kwargs)
return qmake
diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py
index 98644c0..3e5e44b 100644
--- a/mesonbuild/envconfig.py
+++ b/mesonbuild/envconfig.py
@@ -42,6 +42,7 @@ known_cpu_families = (
'arm',
'e2k',
'ia64',
+ 'm68k',
'microblaze',
'mips',
'mips64',
@@ -52,6 +53,7 @@ known_cpu_families = (
'riscv64',
'rl78',
'rx',
+ 's390',
's390x',
'sparc',
'sparc64',
@@ -70,6 +72,7 @@ CPU_FAMILES_64_BIT = [
'mips64',
'ppc64',
'riscv64',
+ 's390x',
'sparc64',
'wasm64',
'x86_64',
@@ -140,6 +143,12 @@ class Properties(HasEnvVarFallback):
def get_sys_root(self) -> T.Optional[T.Union[str, T.List[str]]]:
return self.properties.get('sys_root', None)
+ def get_pkg_config_libdir(self) -> T.Optional[T.List[str]]:
+ p = self.properties.get('pkg_config_libdir', None)
+ if p is None:
+ return p
+ return mesonlib.listify(p)
+
def __eq__(self, other: T.Any) -> 'T.Union[bool, NotImplemented]':
if isinstance(other, type(self)):
return self.properties == other.properties
@@ -305,11 +314,19 @@ class BinaryTable(HasEnvVarFallback):
'rust': 'RUSTC',
'vala': 'VALAC',
+ # Linkers
+ 'c_ld': 'CC_LD',
+ 'cpp_ld': 'CXX_LD',
+ 'd_ld': 'D_LD',
+ 'fortran_ld': 'F_LD',
+ 'objc_ld': 'OBJC_LD',
+ 'objcpp_ld': 'OBJCPP_LD',
+ 'rust_ld': 'RUST_LD',
+
# Binutils
'strip': 'STRIP',
'ar': 'AR',
'windres': 'WINDRES',
- 'ld': 'LD',
# Other tools
'cmake': 'CMAKE',
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 3d4f49a..58c9e99 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -749,7 +749,7 @@ class Environment:
check_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value
override = [] # type: T.List[str]
- value = self.binaries[for_machine].lookup_entry('ld')
+ value = self.binaries[for_machine].lookup_entry(comp_class.language + '_ld')
if value is not None:
override = comp_class.use_linker_args(value[0])
check_args += override
@@ -812,7 +812,7 @@ class Environment:
check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args
override = [] # type: T.List[str]
- value = self.binaries[for_machine].lookup_entry('ld')
+ value = self.binaries[for_machine].lookup_entry(comp_class.language + '_ld')
if value is not None:
override = comp_class.use_linker_args(value[0])
check_args += override
@@ -946,6 +946,7 @@ class Environment:
if 'Emscripten' in out:
cls = EmscriptenCCompiler if lang == 'c' else EmscriptenCPPCompiler
+ self.coredata.add_lang_args(cls.language, cls, for_machine, self)
return cls(
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version)
@@ -966,6 +967,7 @@ class Environment:
full_version = arm_ver_str
cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler
linker = ArmClangDynamicLinker(for_machine, version=version)
+ self.coredata.add_lang_args(cls.language, cls, for_machine, self)
return cls(
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
@@ -1061,12 +1063,14 @@ class Environment:
exe_wrap, full_version=full_version, linker=l)
if 'ARM' in out:
cls = ArmCCompiler if lang == 'c' else ArmCPPCompiler
+ self.coredata.add_lang_args(cls.language, cls, for_machine, self)
linker = ArmDynamicLinker(for_machine, version=version)
return cls(
ccache + compiler, version, for_machine, is_cross,
info, exe_wrap, full_version=full_version, linker=linker)
if 'RX Family' in out:
cls = CcrxCCompiler if lang == 'c' else CcrxCPPCompiler
+ self.coredata.add_lang_args(cls.language, cls, for_machine, self)
linker = CcrxDynamicLinker(for_machine, version=version)
return cls(
ccache + compiler, version, for_machine, is_cross, info,
@@ -1355,6 +1359,7 @@ class Environment:
cc = self.detect_c_compiler(for_machine)
is_link_exe = isinstance(cc.linker, VisualStudioLikeLinkerMixin)
+ override = self.binaries[for_machine].lookup_entry('rust_ld')
for compiler in compilers:
if isinstance(compiler, str):
@@ -1378,33 +1383,47 @@ class Environment:
# the default use that, and second add the necessary arguments
# to rust to use -fuse-ld
- extra_args = {}
- always_args = []
- if is_link_exe:
- compiler.extend(['-C', 'linker={}'.format(cc.linker.exelist[0])])
- extra_args['direct'] = True
- extra_args['machine'] = cc.linker.machine
- elif not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or
- isinstance(cc, GnuCCompiler)):
+ if override is None:
+ extra_args = {}
+ always_args = []
+ if is_link_exe:
+ compiler.extend(['-C', 'linker={}'.format(cc.linker.exelist[0])])
+ extra_args['direct'] = True
+ extra_args['machine'] = cc.linker.machine
+ elif not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or
+ isinstance(cc, GnuCCompiler)):
+ c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0]
+ compiler.extend(['-C', 'linker={}'.format(c)])
+
+ # This trickery with type() gets us the class of the linker
+ # so we can initialize a new copy for the Rust Compiler
+ if is_link_exe:
+ linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist,
+ version=cc.linker.version, **extra_args)
+ else:
+ linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX,
+ always_args=always_args, version=cc.linker.version,
+ **extra_args)
+ elif 'link' in override[0]:
+ linker = self._guess_win_linker(
+ override, RustCompiler, for_machine, use_linker_prefix=False)
+ linker.direct = True
+ else:
+ # We're creating a new type of "C" compiler, that has rust
+ # as it's language. This is gross, but I can't figure out
+ # another way to handle this, because rustc is actually
+ # invoking the c compiler as it's linker.
+ b = type('b', (type(cc), ), {})
+ b.language = RustCompiler.language
+ linker = self._guess_nix_linker(cc.exelist, b, for_machine)
+
+ # Of course, we're not going to use any of that, we just
+ # need it to get the proper arguments to pass to rustc
c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0]
compiler.extend(['-C', 'linker={}'.format(c)])
+ compiler.extend(['-C', 'link-args={}'.format(' '.join(cc.use_linker_args(override[0])))])
- value = self.binaries[for_machine].lookup_entry('ld')
- if value is not None:
- for a in cc.use_linker_args(value[0]):
- always_args.extend(['-C', 'link-arg={}'.format(a)])
-
- # This trickery with type() gets us the class of the linker
- # so we can initialize a new copy for the Rust Compiler
-
- if is_link_exe:
- linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist,
- version=cc.linker.version, **extra_args)
- else:
- linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX,
- always_args=always_args, version=cc.linker.version,
- **extra_args)
-
+ self.coredata.add_lang_args(RustCompiler.language, RustCompiler, for_machine, self)
return RustCompiler(
compiler, version, for_machine, is_cross, info, exe_wrap,
linker=linker)
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index bdbcc38..908a555 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -2868,13 +2868,7 @@ external dependencies (including libraries) must go to "dependencies".''')
return False
return self.add_languages(args, required)
- def get_message_string_arg(self, node):
- # reduce arguments again to avoid flattening posargs
- (posargs, _) = self.reduce_arguments(node.args)
- if len(posargs) != 1:
- raise InvalidArguments('Expected 1 argument, got %d' % len(posargs))
-
- arg = posargs[0]
+ def get_message_string_arg(self, arg):
if isinstance(arg, list):
argstr = stringifyUserArguments(arg)
elif isinstance(arg, dict):
@@ -2888,13 +2882,16 @@ external dependencies (including libraries) must go to "dependencies".''')
return argstr
+ @noArgsFlattening
@noKwargs
def func_message(self, node, args, kwargs):
- argstr = self.get_message_string_arg(node)
- self.message_impl(argstr)
+ if len(args) > 1:
+ FeatureNew('message with more than one argument', '0.54.0').use(self.subproject)
+ args_str = [self.get_message_string_arg(i) for i in args]
+ self.message_impl(args_str)
- def message_impl(self, argstr):
- mlog.log(mlog.bold('Message:'), argstr)
+ def message_impl(self, args):
+ mlog.log(mlog.bold('Message:'), *args)
@noArgsFlattening
@permittedKwargs({'section', 'bool_yn'})
@@ -2938,11 +2935,14 @@ external dependencies (including libraries) must go to "dependencies".''')
if main_summary:
main_summary.dump()
+ @noArgsFlattening
@FeatureNew('warning', '0.44.0')
@noKwargs
def func_warning(self, node, args, kwargs):
- argstr = self.get_message_string_arg(node)
- mlog.warning(argstr, location=node)
+ if len(args) > 1:
+ FeatureNew('warning with more than one argument', '0.54.0').use(self.subproject)
+ args_str = [self.get_message_string_arg(i) for i in args]
+ mlog.warning(*args_str, location=node)
@noKwargs
def func_error(self, node, args, kwargs):
@@ -3244,10 +3244,10 @@ external dependencies (including libraries) must go to "dependencies".''')
d = self.dependency_impl(name, display_name, kwargs)
except Exception:
if not_found_message:
- self.message_impl(not_found_message)
+ self.message_impl([not_found_message])
raise
if not d.found() and not_found_message:
- self.message_impl(not_found_message)
+ self.message_impl([not_found_message])
return d
def dependency_impl(self, name, display_name, kwargs):
@@ -3336,10 +3336,14 @@ external dependencies (including libraries) must go to "dependencies".''')
return fbinfo
def dependency_fallback(self, display_name, kwargs):
+ required = kwargs.get('required', True)
if self.coredata.get_builtin_option('wrap_mode') == WrapMode.nofallback:
mlog.log('Not looking for a fallback subproject for the dependency',
- mlog.bold(display_name), 'because:\nUse of fallback'
+ mlog.bold(display_name), 'because:\nUse of fallback '
'dependencies is disabled.')
+ if required:
+ m = 'Dependency {!r} not found and fallback is disabled'
+ raise DependencyException(m.format(display_name))
return self.notfound_dependency()
elif self.coredata.get_builtin_option('wrap_mode') == WrapMode.forcefallback:
mlog.log('Looking for a fallback subproject for the dependency',
@@ -3350,7 +3354,7 @@ external dependencies (including libraries) must go to "dependencies".''')
dirname, varname = self.get_subproject_infos(kwargs)
sp_kwargs = {
'default_options': kwargs.get('default_options', []),
- 'required': kwargs.get('required', True),
+ 'required': required,
}
self.do_subproject(dirname, 'meson', sp_kwargs)
return self.get_subproject_dep(display_name, dirname, varname, kwargs)
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index 51c5733..0a5c57e 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -246,12 +246,16 @@ class DynamicLinker(metaclass=abc.ABCMeta):
'custom': [],
} # type: T.Dict[str, T.List[str]]
- def _apply_prefix(self, arg: str) -> T.List[str]:
+ def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]:
+ args = [arg] if isinstance(arg, str) else arg
if self.prefix_arg is None:
- return [arg]
+ return args
elif isinstance(self.prefix_arg, str):
- return [self.prefix_arg + arg]
- return self.prefix_arg + [arg]
+ return [self.prefix_arg + arg for arg in args]
+ ret = []
+ for arg in args:
+ ret += self.prefix_arg + [arg]
+ return ret
def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
id_: str, prefix_arg: T.Union[str, T.List[str]],
@@ -276,7 +280,8 @@ class DynamicLinker(metaclass=abc.ABCMeta):
return self.exelist.copy()
def get_accepts_rsp(self) -> bool:
- # TODO: is it really a matter of is_windows or is it for_windows?
+ # rsp files are only used when building on Windows because we want to
+ # avoid issues with quoting and max argument length
return mesonlib.is_windows()
def get_always_args(self) -> T.List[str]:
@@ -795,7 +800,7 @@ class VisualStudioLikeLinkerMixin:
return self._apply_prefix('/MDd')
def get_output_args(self, outputname: str) -> T.List[str]:
- return self._apply_prefix('/MACHINE:' + self.machine) + self._apply_prefix('/OUT:' + outputname)
+ return self._apply_prefix(['/MACHINE:' + self.machine, '/OUT:' + outputname])
def get_always_args(self) -> T.List[str]:
return self._apply_prefix('/nologo') + super().get_always_args()
@@ -809,7 +814,7 @@ class VisualStudioLikeLinkerMixin:
def get_debugfile_args(self, targetfile: str) -> T.List[str]:
pdbarr = targetfile.split('.')[:-1]
pdbarr += ['pdb']
- return self._apply_prefix('/DEBUG') + self._apply_prefix('/PDB:' + '.'.join(pdbarr))
+ return self._apply_prefix(['/DEBUG', '/PDB:' + '.'.join(pdbarr)])
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
# Only since VS2015
@@ -840,6 +845,9 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
super().__init__(exelist or ['link.exe'], for_machine, 'link',
prefix, always_args, machine=machine, version=version, direct=direct)
+ def get_always_args(self) -> T.List[str]:
+ return self._apply_prefix(['/nologo', '/release']) + super().get_always_args()
+
class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py
index 3cfb39a..a86cd43 100644
--- a/mesonbuild/mdist.py
+++ b/mesonbuild/mdist.py
@@ -73,10 +73,12 @@ def process_submodules(dirname):
del_gitfiles(os.path.join(dirname, v))
-def run_dist_scripts(dist_root, dist_scripts):
+def run_dist_scripts(src_root, bld_root, dist_root, dist_scripts):
assert(os.path.isabs(dist_root))
env = os.environ.copy()
env['MESON_DIST_ROOT'] = dist_root
+ env['MESON_SOURCE_ROOT'] = src_root
+ env['MESON_BUILD_ROOT'] = bld_root
for d in dist_scripts:
script = d['exe']
args = d['args']
@@ -121,7 +123,7 @@ def create_dist_git(dist_name, archives, src_root, bld_root, dist_sub, dist_scri
git_clone(sub_src_root, sub_distdir)
else:
shutil.copytree(sub_src_root, sub_distdir)
- run_dist_scripts(distdir, dist_scripts)
+ run_dist_scripts(src_root, bld_root, distdir, dist_scripts)
output_names = []
for a in archives:
compressed_name = distdir + archive_extension[a]
@@ -141,6 +143,8 @@ def hg_have_dirty_index(src_root):
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')
+ if dist_scripts:
+ mlog.warning('dist scripts are not supported in Mercurial projects')
os.makedirs(dist_sub, exist_ok=True)
tarname = os.path.join(dist_sub, dist_name + '.tar')
@@ -149,8 +153,6 @@ def create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, dist_scrip
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')
if 'xztar' in archives:
import lzma
with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf:
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 9ae7b76..85d883b 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -56,6 +56,20 @@ else:
python_command = [sys.executable]
meson_command = None
+GIT = shutil.which('git')
+def git(cmd: T.List[str], workingdir: str, **kwargs) -> subprocess.CompletedProcess:
+ pc = subprocess.run([GIT, '-C', workingdir] + cmd,
+ # Redirect stdin to DEVNULL otherwise git messes up the
+ # console and ANSI colors stop working on Windows.
+ stdin=subprocess.DEVNULL, **kwargs)
+ # Sometimes git calls git recursively, such as `git submodule update
+ # --recursive` which will be without the above workaround, so set the
+ # console mode again just in case.
+ if platform.system().lower() == 'windows':
+ mlog._windows_ansi()
+ return pc
+
+
def set_meson_command(mainfile):
global python_command
global meson_command
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index a37dd4f..dc45a5b 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -26,7 +26,8 @@ from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs
already_warned_objs = set()
class DependenciesHelper:
- def __init__(self, name):
+ def __init__(self, state, name):
+ self.state = state
self.name = name
self.pub_libs = []
self.pub_reqs = []
@@ -73,6 +74,8 @@ class DependenciesHelper:
'''Returns string names of requirements'''
processed_reqs = []
for obj in mesonlib.listify(reqs, unholder=True):
+ if not isinstance(obj, str):
+ FeatureNew('pkgconfig.generate requirement from non-string object', '0.46.0').use(self.state.subproject)
if hasattr(obj, 'generated_pc'):
self._check_generated_pc_deprecation(obj)
processed_reqs.append(obj.generated_pc)
@@ -395,7 +398,7 @@ class PkgConfigModule(ExtensionModule):
if mainlib:
libraries = [mainlib] + libraries
- deps = DependenciesHelper(filebase)
+ deps = DependenciesHelper(state, filebase)
deps.add_pub_libs(libraries)
deps.add_priv_libs(kwargs.get('libraries_private', []))
deps.add_pub_reqs(kwargs.get('requires', []))
diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py
index 39fb4ef..d6f0715 100755
--- a/mesonbuild/msubprojects.py
+++ b/mesonbuild/msubprojects.py
@@ -2,7 +2,7 @@ import os, subprocess
import argparse
from . import mlog
-from .mesonlib import Popen_safe
+from .mesonlib import git, Popen_safe
from .wrap.wrap import API_ROOT, PackageDefinition, Resolver, WrapException
from .wrap import wraptool
@@ -39,16 +39,12 @@ def update_file(wrap, repo_dir, options):
mlog.log(' -> Subproject has not changed, or the new source/patch needs to be extracted on the same location.\n' +
' In that case, delete', mlog.bold(repo_dir), 'and run', mlog.bold('meson --reconfigure'))
-def git(cmd, workingdir):
- return subprocess.check_output(['git', '-C', workingdir] + cmd,
- # Redirect stdin to DEVNULL otherwise git
- # messes up the console and ANSI colors stop
- # working on Windows.
- stdin=subprocess.DEVNULL,
- stderr=subprocess.STDOUT).decode()
+def git_output(cmd, workingdir):
+ return git(cmd, workingdir, check=True, universal_newlines=True,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
def git_show(repo_dir):
- commit_message = git(['show', '--quiet', '--pretty=format:%h%n%d%n%s%n[%an]'], repo_dir)
+ commit_message = git_output(['show', '--quiet', '--pretty=format:%h%n%d%n%s%n[%an]'], repo_dir)
parts = [s.strip() for s in commit_message.split('\n')]
mlog.log(' ->', mlog.yellow(parts[0]), mlog.red(parts[1]), parts[2], mlog.blue(parts[3]))
@@ -57,12 +53,12 @@ def update_git(wrap, repo_dir, options):
mlog.log(' -> Not used.')
return
revision = wrap.get('revision')
- ret = git(['rev-parse', '--abbrev-ref', 'HEAD'], repo_dir).strip()
+ ret = git_output(['rev-parse', '--abbrev-ref', 'HEAD'], repo_dir).strip()
if ret == 'HEAD':
try:
# We are currently in detached mode, just checkout the new revision
- git(['fetch'], repo_dir)
- git(['checkout', revision], repo_dir)
+ git_output(['fetch'], repo_dir)
+ git_output(['checkout', revision], repo_dir)
except subprocess.CalledProcessError as e:
out = e.output.decode().strip()
mlog.log(' -> Could not checkout revision', mlog.cyan(revision))
@@ -72,7 +68,7 @@ def update_git(wrap, repo_dir, options):
elif ret == revision:
try:
# We are in the same branch, pull latest commits
- git(['-c', 'rebase.autoStash=true', 'pull', '--rebase'], repo_dir)
+ git_output(['-c', 'rebase.autoStash=true', 'pull', '--rebase'], repo_dir)
except subprocess.CalledProcessError as e:
out = e.output.decode().strip()
mlog.log(' -> Could not rebase', mlog.bold(repo_dir), 'please fix and try again.')
@@ -84,8 +80,8 @@ def update_git(wrap, repo_dir, options):
# we should rebase it on top of wrap's branch.
if options.rebase:
try:
- git(['fetch'], repo_dir)
- git(['-c', 'rebase.autoStash=true', 'rebase', revision], repo_dir)
+ git_output(['fetch'], repo_dir)
+ git_output(['-c', 'rebase.autoStash=true', 'rebase', revision], repo_dir)
except subprocess.CalledProcessError as e:
out = e.output.decode().strip()
mlog.log(' -> Could not rebase', mlog.bold(repo_dir), 'please fix and try again.')
@@ -97,7 +93,7 @@ def update_git(wrap, repo_dir, options):
' To rebase your branch on top of', mlog.bold(revision), 'use', mlog.bold('--rebase'), 'option.')
return
- git(['submodule', 'update', '--checkout', '--recursive'], repo_dir)
+ git_output(['submodule', 'update', '--checkout', '--recursive'], repo_dir)
git_show(repo_dir)
def update_hg(wrap, repo_dir, options):
@@ -154,7 +150,7 @@ def checkout(wrap, repo_dir, options):
cmd.insert(1, '-b')
mlog.log('Checkout %s in %s...' % (branch_name, wrap.name))
try:
- git(cmd, repo_dir)
+ git_output(cmd, repo_dir)
git_show(repo_dir)
except subprocess.CalledProcessError as e:
out = e.output.decode().strip()
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index abbeb9e..51ad86e 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -28,7 +28,7 @@ import configparser
import typing as T
from . import WrapMode
-from ..mesonlib import ProgressBar, MesonException
+from ..mesonlib import git, GIT, ProgressBar, MesonException
if T.TYPE_CHECKING:
import http.client
@@ -43,49 +43,52 @@ except ImportError:
has_ssl = False
API_ROOT = 'http://wrapdb.mesonbuild.com/v1/'
-req_timeout = 600.0
-ssl_warning_printed = False
-whitelist_subdomain = 'wrapdb.mesonbuild.com'
-
+REQ_TIMEOUT = 600.0
+SSL_WARNING_PRINTED = False
+WHITELIST_SUBDOMAIN = 'wrapdb.mesonbuild.com'
def quiet_git(cmd: T.List[str], workingdir: str) -> T.Tuple[bool, str]:
- git = shutil.which('git')
- if not git:
+ if not GIT:
return False, 'Git program not found.'
- pc = subprocess.run([git, '-C', workingdir] + cmd, universal_newlines=True,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ pc = git(cmd, workingdir, universal_newlines=True,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if pc.returncode != 0:
return False, pc.stderr
return True, pc.stdout
+def verbose_git(cmd: T.List[str], workingdir: str, check: bool = False) -> bool:
+ if not GIT:
+ return False
+ return git(cmd, workingdir, check=check).returncode == 0
+
def whitelist_wrapdb(urlstr: str) -> urllib.parse.ParseResult:
""" raises WrapException if not whitelisted subdomain """
url = urllib.parse.urlparse(urlstr)
if not url.hostname:
raise WrapException('{} is not a valid URL'.format(urlstr))
- if not url.hostname.endswith(whitelist_subdomain):
+ if not url.hostname.endswith(WHITELIST_SUBDOMAIN):
raise WrapException('{} is not a whitelisted WrapDB URL'.format(urlstr))
if has_ssl and not url.scheme == 'https':
raise WrapException('WrapDB did not have expected SSL https url, instead got {}'.format(urlstr))
return url
def open_wrapdburl(urlstring: str) -> 'http.client.HTTPResponse':
- global ssl_warning_printed
+ global SSL_WARNING_PRINTED
url = whitelist_wrapdb(urlstring)
if has_ssl:
try:
- return urllib.request.urlopen(urllib.parse.urlunparse(url), timeout=req_timeout)
+ return urllib.request.urlopen(urllib.parse.urlunparse(url), timeout=REQ_TIMEOUT)
except urllib.error.URLError as excp:
raise WrapException('WrapDB connection failed to {} with error {}'.format(urlstring, excp))
# following code is only for those without Python SSL
nossl_url = url._replace(scheme='http')
- if not ssl_warning_printed:
+ if not SSL_WARNING_PRINTED:
mlog.warning('SSL module not available in {}: WrapDB traffic not authenticated.'.format(sys.executable))
- ssl_warning_printed = True
+ SSL_WARNING_PRINTED = True
try:
- return urllib.request.urlopen(urllib.parse.urlunparse(nossl_url), timeout=req_timeout)
+ return urllib.request.urlopen(urllib.parse.urlunparse(nossl_url), timeout=REQ_TIMEOUT)
except urllib.error.URLError as excp:
raise WrapException('WrapDB connection failed to {} with error {}'.format(urlstring, excp))
@@ -205,8 +208,7 @@ class Resolver:
raise WrapException(m)
def resolve_git_submodule(self) -> bool:
- git = shutil.which('git')
- if not git:
+ if not GIT:
raise WrapException('Git program not found.')
# Are we in a git repository?
ret, out = quiet_git(['rev-parse'], self.subdir_root)
@@ -224,13 +226,12 @@ class Resolver:
raise WrapException('git submodule has merge conflicts')
# Submodule exists, but is deinitialized or wasn't initialized
elif out.startswith('-'):
- if subprocess.run([git, '-C', self.subdir_root,
- 'submodule', 'update', '--init', self.dirname]).returncode == 0:
+ if verbose_git(['submodule', 'update', '--init', self.dirname], self.subdir_root):
return True
raise WrapException('git submodule failed to init')
# Submodule looks fine, but maybe it wasn't populated properly. Do a checkout.
elif out.startswith(' '):
- subprocess.run([git, 'checkout', '.'], cwd=self.dirname)
+ verbose_git(['checkout', '.'], self.dirname)
# Even if checkout failed, try building it anyway and let the user
# handle any problems manually.
return True
@@ -253,8 +254,7 @@ class Resolver:
self.apply_patch()
def get_git(self) -> None:
- git = shutil.which('git')
- if not git:
+ if not GIT:
raise WrapException('Git program not found.')
revno = self.wrap.get('revision')
is_shallow = False
@@ -266,44 +266,33 @@ class Resolver:
if is_shallow and self.is_git_full_commit_id(revno):
# git doesn't support directly cloning shallowly for commits,
# so we follow https://stackoverflow.com/a/43136160
- subprocess.check_call([git, 'init', self.directory], cwd=self.subdir_root)
- subprocess.check_call([git, 'remote', 'add', 'origin', self.wrap.get('url')],
- cwd=self.dirname)
+ verbose_git(['init', self.directory], self.subdir_root, check=True)
+ verbose_git(['remote', 'add', 'origin', self.wrap.get('url')], self.dirname, check=True)
revno = self.wrap.get('revision')
- subprocess.check_call([git, 'fetch', *depth_option, 'origin', revno],
- cwd=self.dirname)
- subprocess.check_call([git, 'checkout', revno], cwd=self.dirname)
+ verbose_git(['fetch', *depth_option, 'origin', revno], self.dirname, check=True)
+ verbose_git(['checkout', revno], self.dirname, check=True)
if self.wrap.values.get('clone-recursive', '').lower() == 'true':
- subprocess.check_call([git, 'submodule', 'update',
- '--init', '--checkout', '--recursive', *depth_option],
- cwd=self.dirname)
+ verbose_git(['submodule', 'update', '--init', '--checkout',
+ '--recursive', *depth_option], self.dirname, check=True)
push_url = self.wrap.values.get('push-url')
if push_url:
- subprocess.check_call([git, 'remote', 'set-url',
- '--push', 'origin', push_url],
- cwd=self.dirname)
+ verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True)
else:
if not is_shallow:
- subprocess.check_call([git, 'clone', self.wrap.get('url'),
- self.directory], cwd=self.subdir_root)
+ verbose_git(['clone', self.wrap.get('url'), self.directory], self.subdir_root, check=True)
if revno.lower() != 'head':
- if subprocess.run([git, 'checkout', revno], cwd=self.dirname).returncode != 0:
- subprocess.check_call([git, 'fetch', self.wrap.get('url'), revno], cwd=self.dirname)
- subprocess.check_call([git, 'checkout', revno], cwd=self.dirname)
+ if not verbose_git(['checkout', revno], self.dirname):
+ verbose_git(['fetch', self.wrap.get('url'), revno], self.dirname, check=True)
+ verbose_git(['checkout', revno], self.dirname, check=True)
else:
- subprocess.check_call([git, 'clone', *depth_option,
- '--branch', revno,
- self.wrap.get('url'),
- self.directory], cwd=self.subdir_root)
+ verbose_git(['clone', *depth_option, '--branch', revno, self.wrap.get('url'),
+ self.directory], self.subdir_root, check=True)
if self.wrap.values.get('clone-recursive', '').lower() == 'true':
- subprocess.check_call([git, 'submodule', 'update',
- '--init', '--checkout', '--recursive', *depth_option],
- cwd=self.dirname)
+ verbose_git(['submodule', 'update', '--init', '--checkout', '--recursive', *depth_option],
+ self.dirname, check=True)
push_url = self.wrap.values.get('push-url')
if push_url:
- subprocess.check_call([git, 'remote', 'set-url',
- '--push', 'origin', push_url],
- cwd=self.dirname)
+ verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True)
def is_git_full_commit_id(self, revno: str) -> bool:
result = False
@@ -335,15 +324,13 @@ class Resolver:
h = hashlib.sha256()
tmpfile = tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False)
url = urllib.parse.urlparse(urlstring)
- if not url.hostname:
- raise WrapException('{} is not a valid URL'.format(urlstring))
- if url.hostname.endswith(whitelist_subdomain):
+ if url.hostname and url.hostname.endswith(WHITELIST_SUBDOMAIN):
resp = open_wrapdburl(urlstring)
- elif whitelist_subdomain in urlstring:
+ elif WHITELIST_SUBDOMAIN in urlstring:
raise WrapException('{} may be a WrapDB-impersonating URL'.format(urlstring))
else:
try:
- resp = urllib.request.urlopen(urlstring, timeout=req_timeout)
+ resp = urllib.request.urlopen(urlstring, timeout=REQ_TIMEOUT)
except urllib.error.URLError:
raise WrapException('could not get {} is the internet available?'.format(urlstring))
with contextlib.closing(resp) as resp:
diff --git a/run_project_tests.py b/run_project_tests.py
index c0adb8e..e480160 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -94,6 +94,7 @@ class AutoDeletedDir:
failing_logs = []
print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ
under_ci = 'CI' in os.environ
+under_xenial_ci = under_ci and ('XENIAL' in os.environ)
do_debug = under_ci or print_debug
no_meson_log_msg = 'No meson-log.txt found.'
@@ -539,7 +540,8 @@ def have_java():
return False
def skippable(suite, test):
- if not under_ci:
+ # Everything is optional when not running on CI, or on Ubuntu 16.04 CI
+ if not under_ci or under_xenial_ci:
return True
if not suite.endswith('frameworks'):
diff --git a/run_tests.py b/run_tests.py
index c811705..4a1d271 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -36,6 +36,26 @@ from mesonbuild.environment import Environment, detect_ninja
from mesonbuild.coredata import backendlist
NINJA_1_9_OR_NEWER = False
+NINJA_CMD = None
+# If we're on CI, just assume we have ninja in PATH and it's new enough because
+# we provide that. This avoids having to detect ninja for every subprocess unit
+# test that we run.
+if 'CI' in os.environ:
+ NINJA_1_9_OR_NEWER = True
+ NINJA_CMD = 'ninja'
+else:
+ # Look for 1.9 to see if https://github.com/ninja-build/ninja/issues/1219
+ # is fixed, else require 1.6 for -w dupbuild=err
+ for v in ('1.9', '1.6'):
+ NINJA_CMD = detect_ninja(v)
+ if NINJA_CMD is not None:
+ if mesonlib.version_compare(v, '>=1.9'):
+ NINJA_1_9_OR_NEWER = True
+ else:
+ mlog.warning('Found ninja <1.9, tests will run slower', once=True)
+ break
+if NINJA_CMD is None:
+ raise RuntimeError('Could not find Ninja v1.6 or newer')
def guess_backend(backend, msbuild_exe: str):
# Auto-detect backend if unspecified
@@ -202,22 +222,8 @@ def get_backend_commands(backend, debug=False):
clean_cmd = cmd + ['-alltargets', 'clean', '-UseNewBuildSystem=FALSE']
test_cmd = cmd + ['-target', 'RUN_TESTS']
elif backend is Backend.ninja:
- global NINJA_1_9_OR_NEWER
- # Look for 1.9 to see if https://github.com/ninja-build/ninja/issues/1219
- # is fixed, else require 1.6 for -w dupbuild=err
- for v in ('1.9', '1.6'):
- ninja_cmd = detect_ninja(v)
- if ninja_cmd is not None:
- if v == '1.9':
- NINJA_1_9_OR_NEWER = True
- else:
- mlog.warning('Found ninja <1.9, tests will run slower', once=True)
- if 'CI' in os.environ:
- raise RuntimeError('Require ninja >= 1.9 when running on Meson CI')
- break
- cmd = [ninja_cmd, '-w', 'dupbuild=err', '-d', 'explain']
- if cmd[0] is None:
- raise RuntimeError('Could not find Ninja v1.6 or newer')
+ global NINJA_CMD
+ cmd = [NINJA_CMD, '-w', 'dupbuild=err', '-d', 'explain']
if debug:
cmd += ['-v']
clean_cmd = cmd + ['clean']
diff --git a/run_unittests.py b/run_unittests.py
index 015167b..ae12f4e 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -32,6 +32,7 @@ import threading
import urllib.error
import urllib.request
import zipfile
+import hashlib
from itertools import chain
from unittest import mock
from configparser import ConfigParser
@@ -43,6 +44,7 @@ from distutils.dir_util import copy_tree
import mesonbuild.mlog
import mesonbuild.depfile
import mesonbuild.compilers
+import mesonbuild.envconfig
import mesonbuild.environment
import mesonbuild.mesonlib
import mesonbuild.coredata
@@ -707,18 +709,20 @@ class InternalTests(unittest.TestCase):
class Mock:
pass
+ dummystate = Mock()
+ dummystate.subproject = 'dummy'
mock = Mock()
mock.pcdep = Mock()
mock.pcdep.name = "some_name"
mock.version_reqs = []
# pkgconfig dependency as lib
- deps = mesonbuild.modules.pkgconfig.DependenciesHelper("thislib")
+ deps = mesonbuild.modules.pkgconfig.DependenciesHelper(dummystate, "thislib")
deps.add_pub_libs([mock])
self.assertEqual(deps.format_reqs(deps.pub_reqs), "some_name")
# pkgconfig dependency as requires
- deps = mesonbuild.modules.pkgconfig.DependenciesHelper("thislib")
+ deps = mesonbuild.modules.pkgconfig.DependenciesHelper(dummystate, "thislib")
deps.add_pub_reqs([mock])
self.assertEqual(deps.format_reqs(deps.pub_reqs), "some_name")
@@ -1227,7 +1231,7 @@ class DataTests(unittest.TestCase):
platform on the CI.
'''
md = None
- with open('docs/markdown/Builtin-options.md') as f:
+ with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f:
md = f.read()
self.assertIsNotNone(md)
env = get_fake_env()
@@ -1247,7 +1251,7 @@ class DataTests(unittest.TestCase):
Builtin-Options.md.
'''
md = None
- with open('docs/markdown/Builtin-options.md') as f:
+ with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f:
md = f.read()
self.assertIsNotNone(md)
@@ -1281,7 +1285,7 @@ class DataTests(unittest.TestCase):
]))
def test_cpu_families_documented(self):
- with open("docs/markdown/Reference-tables.md") as f:
+ with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f:
md = f.read()
self.assertIsNotNone(md)
@@ -1300,7 +1304,7 @@ class DataTests(unittest.TestCase):
'''
Test that each markdown files in docs/markdown is referenced in sitemap.txt
'''
- with open("docs/sitemap.txt") as f:
+ with open("docs/sitemap.txt", encoding='utf-8') as f:
md = f.read()
self.assertIsNotNone(md)
toc = list(m.group(1) for m in re.finditer(r"^\s*(\w.*)$", md, re.MULTILINE))
@@ -1372,6 +1376,7 @@ class DataTests(unittest.TestCase):
class BasePlatformTests(unittest.TestCase):
def setUp(self):
super().setUp()
+ self.maxDiff = None
src_root = os.path.dirname(__file__)
src_root = os.path.join(os.getcwd(), src_root)
self.src_root = src_root
@@ -3618,6 +3623,34 @@ recommended as it is not supported on some platforms''')
self.wipe()
self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env)
+ @skipIfNoPkgconfig
+ @unittest.skipIf(is_windows(), 'Help needed with fixing this test on windows')
+ def test_pkg_config_libdir(self):
+ testdir = os.path.join(self.unit_test_dir,
+ '46 native dep pkgconfig var')
+ with tempfile.NamedTemporaryFile(mode='w', delete=False) as crossfile:
+ crossfile.write(textwrap.dedent(
+ '''[binaries]
+ pkgconfig = 'pkg-config'
+
+ [properties]
+ pkg_config_libdir = [r'{0}']
+
+ [host_machine]
+ system = 'linux'
+ cpu_family = 'arm'
+ cpu = 'armv7'
+ endian = 'little'
+ '''.format(os.path.join(testdir, 'cross_pkgconfig'))))
+ crossfile.flush()
+ self.meson_cross_file = crossfile.name
+
+ env = {'PKG_CONFIG_LIBDIR': os.path.join(testdir,
+ 'native_pkgconfig')}
+ self.init(testdir, extra_args=['-Dstart_native=false'], override_envvars=env)
+ self.wipe()
+ self.init(testdir, extra_args=['-Dstart_native=true'], override_envvars=env)
+
def __reconfigure(self, change_minor=False):
# Set an older version to force a reconfigure from scratch
filename = os.path.join(self.privatedir, 'coredata.dat')
@@ -4162,9 +4195,6 @@ recommended as it is not supported on some platforms''')
self.init(testdir)
self._run(self.mconf_command + [self.builddir])
- # FIXME: The test is failing on Windows CI even if the print looks good.
- # Maybe encoding issue?
- @unittest.skipIf(is_windows(), 'This test fails on Windows CI')
def test_summary(self):
testdir = os.path.join(self.unit_test_dir, '72 summary')
out = self.init(testdir)
@@ -4187,13 +4217,20 @@ recommended as it is not supported on some platforms''')
A number: 1
yes: YES
no: NO
+
+ Subprojects
+ sub: YES
+ sub2: NO
''')
- # Dict ordering is not guaranteed and an exact string comparison randomly
- # fails on the CI because lines are reordered.
expected_lines = expected.split('\n')[1:]
out_start = out.find(expected_lines[0])
out_lines = out[out_start:].split('\n')[:len(expected_lines)]
- self.assertEqual(sorted(expected_lines), sorted(out_lines))
+ if sys.version_info < (3, 7, 0):
+ # Dictionary order is not stable in Python <3.7, so sort the lines
+ # while comparing
+ self.assertEqual(sorted(expected_lines), sorted(out_lines))
+ else:
+ self.assertEqual(expected_lines, out_lines)
class FailureTests(BasePlatformTests):
@@ -4492,6 +4529,19 @@ class FailureTests(BasePlatformTests):
"}['a'] == 2)\n",
r"Assert failed: {k1 : 1}\['a'\] == 2")
+ def test_wrap_nofallback(self):
+ self.assertMesonRaises("dependency('notfound', fallback : ['foo', 'foo_dep'])",
+ r"Dependency \'notfound\' not found and fallback is disabled",
+ extra_args=['--wrap-mode=nofallback'])
+
+ def test_message(self):
+ self.assertMesonOutputs("message('Array:', ['a', 'b'])",
+ r"Message:.* Array: \['a', 'b'\]")
+
+ def test_warning(self):
+ self.assertMesonOutputs("warning('Array:', ['a', 'b'])",
+ r"WARNING:.* Array: \['a', 'b'\]")
+
@unittest.skipUnless(is_windows() or is_cygwin(), "requires Windows (or Windows via Cygwin)")
class WindowsTests(BasePlatformTests):
'''
@@ -4540,6 +4590,14 @@ class WindowsTests(BasePlatformTests):
self.assertTrue(prog.found(), msg='test-script-ext.py not found in PATH')
self.assertPathEqual(prog.get_command()[0], python_command[0])
self.assertPathBasenameEqual(prog.get_path(), 'test-script-ext.py')
+ # Ensure that WindowsApps gets removed from PATH
+ path = os.environ['PATH']
+ if 'WindowsApps' not in path:
+ username = os.environ['USERNAME']
+ appstore_dir = r'C:\Users\{}\AppData\Local\Microsoft\WindowsApps'.format(username)
+ path = os.pathsep + appstore_dir
+ path = ExternalProgram._windows_sanitize_path(path)
+ self.assertNotIn('WindowsApps', path)
def test_ignore_libs(self):
'''
@@ -4624,7 +4682,8 @@ class WindowsTests(BasePlatformTests):
def _check_ld(self, name: str, lang: str, expected: str) -> None:
if not shutil.which(name):
raise unittest.SkipTest('Could not find {}.'.format(name))
- with mock.patch.dict(os.environ, {'LD': name}):
+ envvar = mesonbuild.envconfig.BinaryTable.evarMap['{}_ld'.format(lang)]
+ with mock.patch.dict(os.environ, {envvar: name}):
env = get_fake_env()
try:
comp = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST)
@@ -4644,6 +4703,34 @@ class WindowsTests(BasePlatformTests):
def test_link_environment_variable_rust(self):
self._check_ld('link', 'rust', 'link')
+ def test_pefile_checksum(self):
+ try:
+ import pefile
+ except ImportError:
+ if is_ci():
+ raise
+ raise unittest.SkipTest('pefile module not found')
+ testdir = os.path.join(self.common_test_dir, '6 linkshared')
+ self.init(testdir)
+ self.build()
+ # Test that binaries have a non-zero checksum
+ env = get_fake_env()
+ cc = env.detect_c_compiler(MachineChoice.HOST)
+ cc_id = cc.get_id()
+ ld_id = cc.get_linker_id()
+ dll = glob(os.path.join(self.builddir, '*mycpplib.dll'))[0]
+ exe = os.path.join(self.builddir, 'cppprog.exe')
+ for f in (dll, exe):
+ pe = pefile.PE(f)
+ msg = 'PE file: {!r}, compiler: {!r}, linker: {!r}'.format(f, cc_id, ld_id)
+ if cc_id == 'clang-cl':
+ # Latest clang-cl tested (7.0) does not write checksums out
+ self.assertFalse(pe.verify_checksum(), msg=msg)
+ else:
+ # Verify that a valid checksum was written by all other compilers
+ self.assertTrue(pe.verify_checksum(), msg=msg)
+
+
@unittest.skipUnless(is_osx(), "requires Darwin")
class DarwinTests(BasePlatformTests):
'''
@@ -4830,7 +4917,10 @@ class LinuxlikeTests(BasePlatformTests):
privatedir2 = self.privatedir
os.environ
- env = {'PKG_CONFIG_LIBDIR': os.pathsep.join([privatedir1, privatedir2])}
+ env = {
+ 'PKG_CONFIG_LIBDIR': os.pathsep.join([privatedir1, privatedir2]),
+ 'PKG_CONFIG_SYSTEM_LIBRARY_PATH': '/usr/lib',
+ }
self._run(['pkg-config', 'dependency-test', '--validate'], override_envvars=env)
# pkg-config strips some duplicated flags so we have to parse the
@@ -5876,7 +5966,8 @@ c = ['{0}']
raise unittest.SkipTest('Solaris currently cannot override the linker.')
if not shutil.which(check):
raise unittest.SkipTest('Could not find {}.'.format(check))
- with mock.patch.dict(os.environ, {'LD': name}):
+ envvar = mesonbuild.envconfig.BinaryTable.evarMap['{}_ld'.format(lang)]
+ with mock.patch.dict(os.environ, {envvar: name}):
env = get_fake_env()
comp = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST)
if lang != 'rust' and comp.use_linker_args('foo') == []:
@@ -5908,6 +5999,39 @@ c = ['{0}']
def test_ld_environment_variable_fortran(self):
self._check_ld('ld.gold', 'gold', 'fortran', 'GNU ld.gold')
+ def compute_sha256(self, filename):
+ with open(filename, 'rb') as f:
+ return hashlib.sha256(f.read()).hexdigest()
+
+ def test_wrap_with_file_url(self):
+ testdir = os.path.join(self.unit_test_dir, '73 wrap file url')
+ source_filename = os.path.join(testdir, 'subprojects', 'foo.tar.xz')
+ patch_filename = os.path.join(testdir, 'subprojects', 'foo-patch.tar.xz')
+ wrap_filename = os.path.join(testdir, 'subprojects', 'foo.wrap')
+ source_hash = self.compute_sha256(source_filename)
+ patch_hash = self.compute_sha256(patch_filename)
+ wrap = textwrap.dedent("""\
+ [wrap-file]
+ directory = foo
+
+ source_url = file://{}
+ source_filename = foo.tar.xz
+ source_hash = {}
+
+ patch_url = file://{}
+ patch_filename = foo-patch.tar.xz
+ patch_hash = {}
+ """.format(source_filename, source_hash, patch_filename, patch_hash))
+ with open(wrap_filename, 'w') as f:
+ f.write(wrap)
+ self.init(testdir)
+ self.build()
+ self.run_tests()
+
+ windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'packagecache'))
+ windows_proof_rmtree(os.path.join(testdir, 'subprojects', 'foo'))
+ os.unlink(wrap_filename)
+
def should_run_cross_arm_tests():
return shutil.which('arm-linux-gnueabihf-gcc') and not platform.machine().lower().startswith('arm')
@@ -6766,7 +6890,7 @@ class NativeFileTests(BasePlatformTests):
class CrossFileTests(BasePlatformTests):
- """Tests for cross file functioality not directly related to
+ """Tests for cross file functionality not directly related to
cross compiling.
This is mainly aimed to testing overrides from cross files.
diff --git a/test cases/cmake/5 object library/main.cpp b/test cases/cmake/5 object library/main.cpp
index cdf54f1..9933ab4 100644
--- a/test cases/cmake/5 object library/main.cpp
+++ b/test cases/cmake/5 object library/main.cpp
@@ -1,3 +1,4 @@
+#include <stdlib.h>
#include <iostream>
#include "libA.hpp"
#include "libB.hpp"
diff --git a/test cases/cmake/6 object library no dep/main.cpp b/test cases/cmake/6 object library no dep/main.cpp
index cdf54f1..9933ab4 100644
--- a/test cases/cmake/6 object library no dep/main.cpp
+++ b/test cases/cmake/6 object library no dep/main.cpp
@@ -1,3 +1,4 @@
+#include <stdlib.h>
#include <iostream>
#include "libA.hpp"
#include "libB.hpp"
diff --git a/test cases/common/219 source set configuration_data/all.h b/test cases/common/219 source set configuration_data/all.h
index 728a7f6..e3547df 100644
--- a/test cases/common/219 source set configuration_data/all.h
+++ b/test cases/common/219 source set configuration_data/all.h
@@ -3,5 +3,7 @@ extern void g(void);
extern void h(void);
extern void undefined(void);
-/* No extern here to get a common symbol */
-void (*p)(void);
+/* Defined in nope.c and f.c,
+ * value depends on the source set and configuration used.
+ */
+extern void (*p)(void);
diff --git a/test cases/common/219 source set configuration_data/f.c b/test cases/common/219 source set configuration_data/f.c
index a50ecda..33d2f18 100644
--- a/test cases/common/219 source set configuration_data/f.c
+++ b/test cases/common/219 source set configuration_data/f.c
@@ -1,5 +1,7 @@
#include "all.h"
+void (*p)(void) = (void *)0x12AB34CD;
+
void f(void)
{
}
diff --git a/test cases/common/220 source set dictionary/all.h b/test cases/common/220 source set dictionary/all.h
index 728a7f6..e3547df 100644
--- a/test cases/common/220 source set dictionary/all.h
+++ b/test cases/common/220 source set dictionary/all.h
@@ -3,5 +3,7 @@ extern void g(void);
extern void h(void);
extern void undefined(void);
-/* No extern here to get a common symbol */
-void (*p)(void);
+/* Defined in nope.c and f.c,
+ * value depends on the source set and configuration used.
+ */
+extern void (*p)(void);
diff --git a/test cases/common/220 source set dictionary/f.c b/test cases/common/220 source set dictionary/f.c
index a50ecda..9c5bb1c 100644
--- a/test cases/common/220 source set dictionary/f.c
+++ b/test cases/common/220 source set dictionary/f.c
@@ -1,5 +1,7 @@
#include "all.h"
+void (*p)(void) = (void *)0x1234ABCD;
+
void f(void)
{
}
diff --git a/test cases/common/222 source set realistic example/meson.build b/test cases/common/222 source set realistic example/meson.build
index ea91e29..5b0e495 100644
--- a/test cases/common/222 source set realistic example/meson.build
+++ b/test cases/common/222 source set realistic example/meson.build
@@ -1,7 +1,7 @@
# a sort-of realistic example that combines the sourceset and kconfig
# modules, inspired by QEMU's build system
-project('sourceset-example', 'cpp')
+project('sourceset-example', 'cpp', default_options: ['cpp_std=c++11'])
cppid = meson.get_compiler('cpp').get_id()
if cppid == 'pgi'
diff --git a/test cases/common/52 custom target/depfile/dep.py b/test cases/common/52 custom target/depfile/dep.py
index 476e88b..dc6e6b6 100755
--- a/test cases/common/52 custom target/depfile/dep.py
+++ b/test cases/common/52 custom target/depfile/dep.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import sys, os
from glob import glob
diff --git a/test cases/common/53 custom target chain/my_compiler.py b/test cases/common/53 custom target chain/my_compiler.py
index 9cf4425..d99029b 100755
--- a/test cases/common/53 custom target chain/my_compiler.py
+++ b/test cases/common/53 custom target chain/my_compiler.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import sys
diff --git a/test cases/common/53 custom target chain/my_compiler2.py b/test cases/common/53 custom target chain/my_compiler2.py
index 0191f3f..22ec789 100755
--- a/test cases/common/53 custom target chain/my_compiler2.py
+++ b/test cases/common/53 custom target chain/my_compiler2.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import sys
diff --git a/test cases/common/53 custom target chain/usetarget/subcomp.py b/test cases/common/53 custom target chain/usetarget/subcomp.py
index b5f6eb0..52dc0bb 100755
--- a/test cases/common/53 custom target chain/usetarget/subcomp.py
+++ b/test cases/common/53 custom target chain/usetarget/subcomp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import sys
diff --git a/test cases/common/68 build always/version.h b/test cases/common/68 build always/version.h
index d3fe5c6..7d433f0 100644
--- a/test cases/common/68 build always/version.h
+++ b/test cases/common/68 build always/version.h
@@ -1,3 +1,3 @@
#pragma once
-const char *version_string;
+extern const char *version_string;
diff --git a/test cases/common/69 vcstag/tagprog.c b/test cases/common/69 vcstag/tagprog.c
index 19b7754..27c3cc5 100644
--- a/test cases/common/69 vcstag/tagprog.c
+++ b/test cases/common/69 vcstag/tagprog.c
@@ -1,6 +1,6 @@
#include<stdio.h>
-const char *vcstag;
+extern const char *vcstag;
int main(void) {
printf("Version is %s\n", vcstag);
diff --git a/test cases/common/99 manygen/subdir/manygen.py b/test cases/common/99 manygen/subdir/manygen.py
index d46b2a8..32ea63c 100755
--- a/test cases/common/99 manygen/subdir/manygen.py
+++ b/test cases/common/99 manygen/subdir/manygen.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
from __future__ import print_function
diff --git a/test cases/cuda/11 cuda dependency (nvcc)/version_reqs/prog.cu b/test cases/cuda/11 cuda dependency (nvcc)/version_reqs/prog.cu
index 5668830..bc90081 100644
--- a/test cases/cuda/11 cuda dependency (nvcc)/version_reqs/prog.cu
+++ b/test cases/cuda/11 cuda dependency (nvcc)/version_reqs/prog.cu
@@ -9,20 +9,21 @@ int cuda_devices(void) {
int main(void) {
std::cout << "Compiled against CUDA version: " << CUDART_VERSION << "\n";
+
int runtime_version = 0;
- cudaError_t r = cudaRuntimeGetVersion(&runtime_version);
- if (r != cudaSuccess) {
- std::cout << "Couldn't obtain CUDA runtime version (error " << r << "). Exiting.\n";
- return -1;
+ switch (cudaError_t r = cudaRuntimeGetVersion(&runtime_version)) {
+ case cudaSuccess:
+ std::cout << "CUDA runtime version: " << runtime_version << "\n";
+ break;
+ case cudaErrorNoDevice:
+ std::cout << "No CUDA hardware found. Exiting.\n";
+ return 0;
+ default:
+ std::cout << "Couldn't obtain CUDA runtime version (error " << r << "). Exiting.\n";
+ return -1;
}
- std::cout << "CUDA runtime version: " << runtime_version << "\n";
int n = cuda_devices();
- if (n == 0) {
- std::cout << "No CUDA hardware found. Exiting.\n";
- return 0;
- }
-
std::cout << "Found " << n << " CUDA devices.\n";
return 0;
}
diff --git a/test cases/fortran/12 submodule/meson.build b/test cases/fortran/12 submodule/meson.build
index 624e567..204a36b 100644
--- a/test cases/fortran/12 submodule/meson.build
+++ b/test cases/fortran/12 submodule/meson.build
@@ -1,6 +1,11 @@
project('submodule single level', 'fortran',
meson_version: '>= 0.50.0')
+fortc = meson.get_compiler('fortran')
+if fortc.get_id() == 'gcc' and fortc.version().version_compare('<6.0')
+ error('MESON_SKIP_TEST need gfortran >= 6.0 for submodule support')
+endif
+
hier2 = executable('single', 'parent.f90', 'child.f90')
test('single-level hierarchy', hier2)
diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build
index b528dca..eec8728 100644
--- a/test cases/frameworks/1 boost/meson.build
+++ b/test cases/frameworks/1 boost/meson.build
@@ -40,14 +40,10 @@ if(python2dep.found() and host_machine.system() == 'linux')
# on the installed version of python (and hope that they match the version boost
# was compiled against)
py2version_string = ''.join(python2dep.version().split('.'))
- bpython2dep = dependency('boost', modules : ['python' + py2version_string])
+ bpython2dep = dependency('boost', modules : ['python' + py2version_string], required: false, disabler: true)
else
# if we have an older version of boost, we need to use the old module names
- bpython2dep = dependency('boost', modules : ['python'])
- endif
-
- if not (bpython2dep.found())
- bpython2dep = disabler()
+ bpython2dep = dependency('boost', modules : ['python'], required: false, disabler: true)
endif
else
python2dep = disabler()
@@ -57,13 +53,9 @@ endif
if(python3dep.found() and host_machine.system() == 'linux')
if(dep.version().version_compare('>=1.67'))
py3version_string = ''.join(python3dep.version().split('.'))
- bpython3dep = dependency('boost', modules : ['python' + py3version_string])
+ bpython3dep = dependency('boost', modules : ['python' + py3version_string], required: false, disabler: true)
else
- bpython3dep = dependency('boost', modules : ['python3'])
- endif
-
- if not (bpython3dep.found())
- bpython3dep = disabler()
+ bpython3dep = dependency('boost', modules : ['python3'], required: false, disabler: true)
endif
else
python3dep = disabler()
@@ -90,7 +82,7 @@ test('Boost extralib test', extralibexe)
python2interpreter = find_program(python2.path(), required: false, disabler: true)
test('Boost Python2', python2interpreter, args: ['./test_python_module.py', meson.current_build_dir()], workdir: meson.current_source_dir(), depends: python2module)
python3interpreter = find_program(python3.path(), required: false, disabler: true)
-test('Boost Python3', python3interpreter, args: ['./test_python_module.py', meson.current_build_dir()], workdir: meson.current_source_dir(), depends: python2module)
+test('Boost Python3', python3interpreter, args: ['./test_python_module.py', meson.current_build_dir()], workdir: meson.current_source_dir(), depends: python3module)
subdir('partial_dep')
diff --git a/test cases/frameworks/31 curses/main.c b/test cases/frameworks/31 curses/main.c
new file mode 100644
index 0000000..07d73f5
--- /dev/null
+++ b/test cases/frameworks/31 curses/main.c
@@ -0,0 +1,7 @@
+#include "curses.h"
+
+int main(void) {
+initscr();
+endwin();
+return 0;
+} \ No newline at end of file
diff --git a/test cases/frameworks/31 curses/meson.build b/test cases/frameworks/31 curses/meson.build
new file mode 100644
index 0000000..21483fb
--- /dev/null
+++ b/test cases/frameworks/31 curses/meson.build
@@ -0,0 +1,9 @@
+project('curses', 'c')
+
+curses = dependency('curses', required: false)
+if not curses.found()
+ error('MESON_SKIP_TEST: Curses library not found')
+endif
+
+exec = executable('basic', 'main.c', dependencies: curses)
+# didn't run the test because in general graphics fail on CI
diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build
index 15fd822..7934572 100644
--- a/test cases/frameworks/4 qt/meson.build
+++ b/test cases/frameworks/4 qt/meson.build
@@ -21,19 +21,25 @@ foreach qt : ['qt4', 'qt5']
error('Invalid qt dep incorrectly found!')
endif
- # This test should be skipped if qt5 isn't found
- if qt == 'qt5'
+ # This test should be skipped if the required version of Qt isn't found
+ #
+ # (In the CI environment, the specified version of Qt is definitely present.
+ # An unexpected skip here is treated as a failure, so we are testing that the
+ # detection mechanism is able to find Qt.)
+ needed_qt = get_option('required').to_lower()
+ required = (qt == needed_qt)
+ if required
dep = dependency(qt, modules : ['Core'], required : false, method : get_option('method'))
if not dep.found()
- error('MESON_SKIP_TEST qt5 not found.')
+ error('MESON_SKIP_TEST @0@ not found.'.format(needed_qt))
endif
endif
# Ensure that the "no-Core-module-specified" code branch is hit
- nocoredep = dependency(qt, modules : ['Gui'], required : qt == 'qt5', method : get_option('method'))
+ nocoredep = dependency(qt, modules : ['Gui'], required : required, method : get_option('method'))
- # If qt4 modules are found, test that. qt5 is required.
- qtdep = dependency(qt, modules : qt_modules, main : true, private_headers: true, required : qt == 'qt5', method : get_option('method'))
+ # If 'qt' modules are found, test that.
+ qtdep = dependency(qt, modules : qt_modules, main : true, private_headers: true, required : required, method : get_option('method'))
if qtdep.found()
qtmodule = import(qt)
@@ -77,6 +83,7 @@ foreach qt : ['qt4', 'qt5']
qtcore = dependency(qt, modules : 'Core', method : get_option('method'))
qtcoreapp = executable(qt + 'core', 'q5core.cpp',
+ cpp_args: '-DQT="@0@"'.format(qt),
dependencies : qtcore)
test(qt + 'test', qtcoreapp)
diff --git a/test cases/frameworks/4 qt/meson_options.txt b/test cases/frameworks/4 qt/meson_options.txt
index bc1069e..223f4fb 100644
--- a/test cases/frameworks/4 qt/meson_options.txt
+++ b/test cases/frameworks/4 qt/meson_options.txt
@@ -1 +1,2 @@
option('method', type : 'string', value : 'auto', description : 'The method to use to find Qt')
+option('required', type : 'string', value : 'qt5', description : 'The version of Qt which is required to be present')
diff --git a/test cases/frameworks/4 qt/q5core.cpp b/test cases/frameworks/4 qt/q5core.cpp
index 25b80b8..44581a6 100644
--- a/test cases/frameworks/4 qt/q5core.cpp
+++ b/test cases/frameworks/4 qt/q5core.cpp
@@ -15,7 +15,7 @@ int main(int argc, char **argv) {
app.installTranslator(&qtTranslator);
QTranslator myappTranslator;
- if(!myappTranslator.load("qt5core_fr") )
+ if(!myappTranslator.load(QT "core_fr") )
return 1;
app.installTranslator(&myappTranslator);
diff --git a/test cases/frameworks/6 gettext/meson.build b/test cases/frameworks/6 gettext/meson.build
index 09ef982..afa24b1 100644
--- a/test cases/frameworks/6 gettext/meson.build
+++ b/test cases/frameworks/6 gettext/meson.build
@@ -5,6 +5,11 @@ if not gettext.found()
error('MESON_SKIP_TEST gettext not found.')
endif
+xgettext = find_program('xgettext', required: false)
+if not xgettext.found()
+ error('MESON_SKIP_TEST xgettext not found.')
+endif
+
if not meson.get_compiler('c').has_header('libintl.h')
error('MESON_SKIP_TEST libintl.h not found.')
endif
diff --git a/test cases/frameworks/7 gnome/meson.build b/test cases/frameworks/7 gnome/meson.build
index 03335b8..e7ba565 100644
--- a/test cases/frameworks/7 gnome/meson.build
+++ b/test cases/frameworks/7 gnome/meson.build
@@ -5,6 +5,11 @@ if not glib.found()
error('MESON_SKIP_TEST glib not found.')
endif
+gir = dependency('gobject-introspection-1.0', required: false)
+if not gir.found()
+ error('MESON_SKIP_TEST gobject-introspection not found.')
+endif
+
python3 = import('python3')
py3 = python3.find_python()
if run_command(py3, '-c', 'import gi;').returncode() != 0
diff --git a/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake b/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake
index 9e68ac6..4f12706 100644
--- a/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake
+++ b/test cases/linuxlike/13 cmake dependency/cmake/FindSomethingLikeZLIB.cmake
@@ -1,6 +1,43 @@
find_package(ZLIB)
include(CMakeFindDependencyMacro)
+include(CheckCXXSourceRuns)
+include(CheckCSourceRuns)
+
+check_cxx_source_runs(
+"
+#include <iostream>
+
+using namespace std;
+
+int main(void) {
+ cout << \"Hello World\" << endl;
+ return 0;
+}
+"
+CXX_CODE_RAN
+)
+
+check_c_source_runs(
+"
+#include <stdio.h>
+
+int main(void) {
+ printf(\"Hello World\");
+ return 0;
+}
+"
+C_CODE_RAN
+)
+
+if(NOT CXX_CODE_RAN)
+ message(FATAL_ERROR "Running CXX source code failed")
+endif()
+
+if(NOT C_CODE_RAN)
+ message(FATAL_ERROR "Running C source code failed")
+endif()
+
find_dependency(Threads)
if(ZLIB_FOUND OR ZLIB_Found)
diff --git a/test cases/linuxlike/13 cmake dependency/meson.build b/test cases/linuxlike/13 cmake dependency/meson.build
index 7753550..a76b327 100644
--- a/test cases/linuxlike/13 cmake dependency/meson.build
+++ b/test cases/linuxlike/13 cmake dependency/meson.build
@@ -1,6 +1,6 @@
# this test can ONLY be run successfully from run_project_test.py
# due to use of setup_env.json
-project('external CMake dependency', 'c')
+project('external CMake dependency', ['c', 'cpp'])
if not find_program('cmake', required: false).found()
error('MESON_SKIP_TEST cmake binary not available.')
diff --git a/test cases/linuxlike/14 static dynamic linkage/verify_static.py b/test cases/linuxlike/14 static dynamic linkage/verify_static.py
index 66bf08b..594f194 100755
--- a/test cases/linuxlike/14 static dynamic linkage/verify_static.py
+++ b/test cases/linuxlike/14 static dynamic linkage/verify_static.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
"""Test script that checks if zlib was statically linked to executable"""
import subprocess
import sys
diff --git a/test cases/linuxlike/15 ld binary/meson.build b/test cases/linuxlike/15 ld binary/meson.build
new file mode 100644
index 0000000..987763e
--- /dev/null
+++ b/test cases/linuxlike/15 ld binary/meson.build
@@ -0,0 +1,4 @@
+project('ld binary')
+
+ld = find_program('ld')
+assert(run_command(ld, '--version').returncode() == 0)
diff --git a/test cases/unit/11 cross prog/some_cross_tool.py b/test cases/unit/11 cross prog/some_cross_tool.py
index 1edd10f..4a473e2 100755
--- a/test cases/unit/11 cross prog/some_cross_tool.py
+++ b/test cases/unit/11 cross prog/some_cross_tool.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
from __future__ import print_function
diff --git a/test cases/unit/11 cross prog/sometool.py b/test cases/unit/11 cross prog/sometool.py
index 4c0e3b1..2ac5680 100755
--- a/test cases/unit/11 cross prog/sometool.py
+++ b/test cases/unit/11 cross prog/sometool.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
from __future__ import print_function
diff --git a/test cases/unit/39 python extmodule/blaster.py b/test cases/unit/39 python extmodule/blaster.py
index 163b6d4..8bfe9cf 100755
--- a/test cases/unit/39 python extmodule/blaster.py
+++ b/test cases/unit/39 python extmodule/blaster.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import sys
import tachyon
diff --git a/test cases/unit/61 identity cross/build_wrapper.py b/test cases/unit/61 identity cross/build_wrapper.py
index 22e8b5d..b5fe7bb 100755
--- a/test cases/unit/61 identity cross/build_wrapper.py
+++ b/test cases/unit/61 identity cross/build_wrapper.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import subprocess, sys
diff --git a/test cases/unit/61 identity cross/host_wrapper.py b/test cases/unit/61 identity cross/host_wrapper.py
index 5b4eed8..e88577c 100755
--- a/test cases/unit/61 identity cross/host_wrapper.py
+++ b/test cases/unit/61 identity cross/host_wrapper.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import subprocess, sys
diff --git a/test cases/unit/73 wrap file url/meson.build b/test cases/unit/73 wrap file url/meson.build
new file mode 100644
index 0000000..3bd3b25
--- /dev/null
+++ b/test cases/unit/73 wrap file url/meson.build
@@ -0,0 +1,4 @@
+project('test wrap with file url')
+
+exe = subproject('foo').get_variable('foo_exe')
+test('test1', exe)
diff --git a/test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xz b/test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xz
new file mode 100644
index 0000000..fdb026c
--- /dev/null
+++ b/test cases/unit/73 wrap file url/subprojects/foo-patch.tar.xz
Binary files differ
diff --git a/test cases/unit/73 wrap file url/subprojects/foo.tar.xz b/test cases/unit/73 wrap file url/subprojects/foo.tar.xz
new file mode 100644
index 0000000..2ed6ab4
--- /dev/null
+++ b/test cases/unit/73 wrap file url/subprojects/foo.tar.xz
Binary files differ
diff --git a/test cases/windows/16 gui app/gui_app_tester.py b/test cases/windows/16 gui app/gui_app_tester.py
index 9cba806..53e7649 100644
--- a/test cases/windows/16 gui app/gui_app_tester.py
+++ b/test cases/windows/16 gui app/gui_app_tester.py
@@ -1,26 +1,19 @@
#!/usr/bin/env python3
-import re
-import subprocess
+import os
import sys
+try:
+ import pefile
+except ImportError:
+ if 'CI' in os.environ:
+ raise
+ # Skip the test if not on CI
+ sys.exit(77)
-tool = sys.argv[1]
-executable = sys.argv[2]
-expected = int(sys.argv[3])
-actual = -1
+executable = sys.argv[1]
+expected = int(sys.argv[2])
-if 'objdump' in tool:
- result = subprocess.check_output([tool, '-p', executable]).decode()
- match = re.search(r'^Subsystem\s+(\d+)', result, re.MULTILINE)
-elif 'dumpbin' in tool:
- result = subprocess.check_output([tool, '/headers', executable]).decode()
- match = re.search(r'^\s*(\d+) subsystem(?! version)', result, re.MULTILINE)
-else:
- print('unknown tool')
- sys.exit(1)
-
-if match:
- actual = int(match.group(1))
+actual = pefile.PE(executable).dump_dict()['OPTIONAL_HEADER']['Subsystem']['Value']
print('subsystem expected: %d, actual: %d' % (expected, actual))
sys.exit(0 if (expected == actual) else 1)
diff --git a/test cases/windows/16 gui app/meson.build b/test cases/windows/16 gui app/meson.build
index 224d708..1570555 100644
--- a/test cases/windows/16 gui app/meson.build
+++ b/test cases/windows/16 gui app/meson.build
@@ -17,10 +17,5 @@ console_prog = executable('console_prog', 'console_prog.c', gui_app: false)
tester = find_program('gui_app_tester.py')
-tool = find_program('objdump', 'dumpbin', required: false)
-# TODO: when 'llvm-objdump -f' emits the subsystem type, we could use that also
-
-if tool.found()
- test('is_gui', tester, args: [tool.path(), gui_prog, '2'])
- test('not_gui', tester, args: [tool.path(), console_prog, '3'])
-endif
+test('is_gui', tester, args: [gui_prog, '2'])
+test('not_gui', tester, args: [console_prog, '3'])
diff --git a/test cases/windows/8 find program/test-script b/test cases/windows/8 find program/test-script
index d105a81..e764165 100644
--- a/test cases/windows/8 find program/test-script
+++ b/test cases/windows/8 find program/test-script
@@ -1,3 +1,3 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
print('1')