aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci_frameworks.yml86
-rw-r--r--.github/workflows/macos.yml85
-rw-r--r--.github/workflows/msys2.yml10
-rw-r--r--.travis.yml5
-rwxr-xr-xci/travis_install.sh17
-rwxr-xr-xci/travis_script.sh41
-rw-r--r--docs/markdown/Adding-new-projects-to-wrapdb.md110
-rw-r--r--docs/markdown/Getting-meson.md9
-rw-r--r--docs/markdown/Reference-manual.md6
-rw-r--r--docs/markdown/Tutorial.md50
-rw-r--r--docs/markdown/snippets/keys_of_configuration_data.md4
-rw-r--r--mesonbuild/backend/ninjabackend.py18
-rw-r--r--mesonbuild/build.py9
-rw-r--r--mesonbuild/compilers/c.py187
-rw-r--r--mesonbuild/compilers/compilers.py2
-rw-r--r--mesonbuild/compilers/cpp.py74
-rw-r--r--mesonbuild/compilers/cuda.py8
-rw-r--r--mesonbuild/compilers/fortran.py37
-rw-r--r--mesonbuild/compilers/mixins/emscripten.py4
-rw-r--r--mesonbuild/compilers/rust.py18
-rw-r--r--mesonbuild/dependencies/base.py6
-rw-r--r--mesonbuild/depfile.py2
-rw-r--r--mesonbuild/environment.py67
-rw-r--r--mesonbuild/interpreter.py16
-rw-r--r--mesonbuild/interpreterbase.py4
-rw-r--r--mesonbuild/mlog.py5
-rw-r--r--mesonbuild/modules/gnome.py13
-rw-r--r--mesonbuild/modules/sourceset.py4
-rw-r--r--mesonbuild/msetup.py2
-rw-r--r--mesonbuild/mtest.py370
-rw-r--r--mesonbuild/scripts/clangformat.py7
-rw-r--r--mesonbuild/scripts/clangtidy.py11
-rwxr-xr-xrun_project_tests.py4
-rwxr-xr-xrun_unittests.py68
-rw-r--r--test cases/common/14 configure file/meson.build1
-rwxr-xr-xtest cases/common/231 external project/libfoo/configure2
-rw-r--r--test cases/common/28 multiline string/meson.build2
-rw-r--r--test cases/failing/76 link with shared module on osx/test.json2
-rw-r--r--test cases/frameworks/34 gir static lib/meson.build18
-rw-r--r--test cases/frameworks/34 gir static lib/statichelper/meson-sample.c126
-rw-r--r--test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in22
-rw-r--r--test cases/frameworks/34 gir static lib/statichelper/meson.build22
-rw-r--r--test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c124
-rw-r--r--test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h17
-rw-r--r--test cases/frameworks/34 gir static lib/subdir/gir/meson.build28
-rw-r--r--test cases/frameworks/34 gir static lib/subdir/gir/prog.c12
-rw-r--r--test cases/frameworks/34 gir static lib/test.json8
-rw-r--r--test cases/frameworks/7 gnome/mkenums/enums.c.in8
-rw-r--r--test cases/frameworks/7 gnome/mkenums/enums2.c.in8
-rw-r--r--test cases/frameworks/7 gnome/mkenums/meson.build8
-rw-r--r--test cases/frameworks/8 flex/lexer.l3
-rw-r--r--test cases/frameworks/8 flex/parser.y5
-rw-r--r--test cases/rust/2 sharedlib/meson.build4
-rw-r--r--test cases/rust/4 polyglot/meson.build4
-rw-r--r--test cases/unit/59 introspect buildoptions/meson.build2
-rw-r--r--test cases/vala/8 generated sources/dependency-generated/enum-types.c.template8
56 files changed, 1175 insertions, 618 deletions
diff --git a/.github/workflows/ci_frameworks.yml b/.github/workflows/ci_frameworks.yml
deleted file mode 100644
index 1ace2a6..0000000
--- a/.github/workflows/ci_frameworks.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-name: ci_frameworks
-
-on:
- push:
- paths:
- - "mesonbuild/dependencies/**"
- - "test cases/frameworks/**"
- - ".github/workflows/ci_frameworks.yml"
- pull_request:
- paths:
- - "mesonbuild/dependencies/**"
- - "test cases/frameworks/**"
- - ".github/workflows/ci_frameworks.yml"
-
-jobs:
-
- scalapackMacOS:
- runs-on: macos-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: '3.x'
- - run: python -m pip install -e .
- - run: brew install pkg-config ninja gcc openmpi lapack scalapack
- - run: meson setup "test cases/frameworks/30 scalapack" build
- - run: meson compile -C build
- - uses: actions/upload-artifact@v1
- if: failure()
- with:
- name: Scalapack_Mac_build
- path: build/meson-logs/meson-log.txt
- - run: meson test -C build -v
- - uses: actions/upload-artifact@v1
- if: failure()
- with:
- name: Scalapack_Mac_test
- path: build/meson-logs/testlog.txt
-
- HDF5macos:
- runs-on: macos-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: '3.x'
- - run: python -m pip install -e .
- - run: brew install pkg-config ninja gcc hdf5
- - run: meson setup "test cases/frameworks/25 hdf5" build -Dmethod=config-tool
- - run: meson compile -C build
- - uses: actions/upload-artifact@v1
- if: failure()
- with:
- name: HDF5_Mac_build
- path: build/meson-logs/meson-log.txt
- - run: meson test -C build -v
- - uses: actions/upload-artifact@v1
- if: failure()
- with:
- name: HDF5_Mac_test
- path: build/meson-logs/testlog.txt
-
- Qt4macos:
- runs-on: macos-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- 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: meson compile -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/macos.yml b/.github/workflows/macos.yml
new file mode 100644
index 0000000..bf559e8
--- /dev/null
+++ b/.github/workflows/macos.yml
@@ -0,0 +1,85 @@
+name: macos
+
+on:
+ push:
+ paths:
+ - "mesonbuild/**"
+ - "test cases/**"
+ - ".github/workflows/macos.yml"
+ pull_request:
+ paths:
+ - "mesonbuild/**"
+ - "test cases/**"
+ - ".github/workflows/macos.yml"
+
+jobs:
+ unittests-appleclang:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: '3.x'
+ - run: |
+ python -m pip install --upgrade pip
+ python -m pip install pytest pytest-xdist jsonschema
+ - run: brew install pkg-config ninja llvm qt
+ - env:
+ CPPFLAGS: "-I/usr/local/include"
+ LDFLAGS: "-L/usr/local/lib"
+ MESON_UNIT_TEST_BACKEND: ninja
+ # These cannot evaluate anything, so we cannot set PATH or SDKROOT here
+ run: |
+ export SDKROOT="$(xcodebuild -version -sdk macosx Path)"
+ export PATH="$HOME/tools:/usr/local/opt/qt/bin:$PATH:$(brew --prefix llvm)/bin"
+ ./run_unittests.py
+
+ project-tests-appleclang:
+ runs-on: macos-latest
+ strategy:
+ matrix:
+ unity: ["on", "off"]
+ steps:
+ - uses: actions/checkout@v2
+ # use python3 from homebrew because it is a valid framework, unlike the actions one:
+ # https://github.com/actions/setup-python/issues/58
+ - run: brew install pkg-config ninja llvm qt boost ldc hdf5 openmpi lapack scalapack sdl2 python3
+ - run: |
+ python3 -m pip install --upgrade setuptools
+ python3 -m pip install --upgrade pip
+ python3 -m pip install cython
+ - env:
+ CPPFLAGS: "-I/usr/local/include"
+ LDFLAGS: "-L/usr/local/lib"
+ MESON_ARGS: --unity=${{ matrix.unity }}
+ CI: 1
+ # These cannot evaluate anything, so we cannot set PATH or SDKROOT here
+ run: |
+ export SDKROOT="$(xcodebuild -version -sdk macosx Path)"
+ export PATH="$HOME/tools:/usr/local/opt/qt/bin:$PATH:$(brew --prefix llvm)/bin"
+ ./run_project_tests.py --backend=ninja
+
+ Qt4macos:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ 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: meson compile -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/msys2.yml b/.github/workflows/msys2.yml
index 57a3f52..642e1de 100644
--- a/.github/workflows/msys2.yml
+++ b/.github/workflows/msys2.yml
@@ -2,7 +2,15 @@ name: msys2
on:
push:
+ paths:
+ - "mesonbuild/**"
+ - "test cases/**"
+ - ".github/workflows/msys.yml"
pull_request:
+ paths:
+ - "mesonbuild/**"
+ - "test cases/**"
+ - ".github/workflows/msys.yml"
jobs:
test:
@@ -83,4 +91,4 @@ jobs:
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.NAME }}
- path: meson-test-run.* \ No newline at end of file
+ path: meson-test-run.*
diff --git a/.travis.yml b/.travis.yml
index ab317be..9f61c96 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,6 @@ branches:
os:
- linux
- - osx
compiler:
- gcc
@@ -25,10 +24,6 @@ services:
- docker
matrix:
- exclude:
- # On OS X gcc is just a wrapper around clang, so don't waste time testing that
- - os: osx
- compiler: gcc
include:
# Test cross builds separately, they do not use the global compiler
# Also hijack one cross build to test long commandline handling codepath (and avoid overloading Travis)
diff --git a/ci/travis_install.sh b/ci/travis_install.sh
index d9d308a..bbeb100 100755
--- a/ci/travis_install.sh
+++ b/ci/travis_install.sh
@@ -4,19 +4,6 @@ set -e
msg() { echo -e "\x1b[1;32mINFO: \x1b[37m$*\x1b[0m"; }
-if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
- msg "Running OSX setup"
- brew update
- # Run one macOS build with pkg-config available (pulled in by qt), and the
- # other (unity=on) without pkg-config
- brew install qt ldc llvm ninja
- if [[ "$MESON_ARGS" =~ .*unity=on.* ]]; then
- which pkg-config && rm -f $(which pkg-config)
- fi
- python3 -m pip install jsonschema
-elif [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
- msg "Running Linux setup"
- docker pull mesonbuild/eoan
-fi
-
+msg "Running Linux setup"
+docker pull mesonbuild/eoan
msg "Setup finished"
diff --git a/ci/travis_script.sh b/ci/travis_script.sh
index 7e26b52..e60e3a3 100755
--- a/ci/travis_script.sh
+++ b/ci/travis_script.sh
@@ -4,16 +4,15 @@ set -e
msg() { echo -e "\x1b[1;32mINFO: \x1b[37m$*\x1b[0m"; }
-if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
- # TODO enable coverage
- #curl -s https://codecov.io/bash > upload.sh
- #chmod +x upload.sh
+# TODO enable coverage
+#curl -s https://codecov.io/bash > upload.sh
+#chmod +x upload.sh
- # We need to copy the current checkout inside the Docker container,
- # because it has the MR id to be tested checked out.
+# We need to copy the current checkout inside the Docker container,
+# because it has the MR id to be tested checked out.
- msg "Generating runner:"
- cat <<EOF | tee run.sh
+msg "Generating runner:"
+cat <<EOF | tee run.sh
#!/bin/bash
set -e
@@ -50,23 +49,9 @@ ADD . /root
EOF
- msg "Building the docker image..."
- docker build -t test_img .
-
- msg "Start running tests"
- #ci_env=`bash <(curl -s https://codecov.io/env)`
- docker run --security-opt seccomp:unconfined test_img /root/run.sh
-
-elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
- # Ensure that llvm is added after $PATH, otherwise the clang from that llvm install will be used instead of the native apple clang.
- export SDKROOT=$(xcodebuild -version -sdk macosx Path)
- export CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib
- export OBJC=$CC
- export OBJCXX=$CXX
- export PATH=$HOME/tools:/usr/local/opt/qt/bin:$PATH:$(brew --prefix llvm)/bin
- if test "$MESON_RSP_THRESHOLD" != ""
- then
- export MESON_RSP_THRESHOLD=$MESON_RSP_THRESHOLD
- fi
- ./run_tests.py $RUN_TESTS_ARGS --backend=ninja -- $MESON_ARGS
-fi
+msg "Building the docker image..."
+docker build -t test_img .
+
+msg "Start running tests"
+#ci_env=`bash <(curl -s https://codecov.io/env)`
+docker run --security-opt seccomp:unconfined test_img /root/run.sh
diff --git a/docs/markdown/Adding-new-projects-to-wrapdb.md b/docs/markdown/Adding-new-projects-to-wrapdb.md
index a266379..5bdadfa 100644
--- a/docs/markdown/Adding-new-projects-to-wrapdb.md
+++ b/docs/markdown/Adding-new-projects-to-wrapdb.md
@@ -3,29 +3,34 @@
## How it works
-Each wrap repository has a master branch with only one initial commit and *no* wrap files.
-And that is the only commit ever made on that branch.
-
-For every release of a project a new branch is created. The new branch is named after the
-the upstream release number (e.g. `1.0.0`). This branch holds a wrap file for
-this particular release.
-
-There are two types of wraps on WrapDB - regular wraps and wraps with Meson build
-definition patches. A wrap file in a repository on WrapDB must have a name `upstream.wrap`.
-
-Wraps with Meson build definition patches work in much the same way as Debian:
-we take the unaltered upstream source package and add a new build system to it as a patch.
-These build systems are stored as Git repositories on GitHub. They only contain build definition files.
-You may also think of them as an overlay to upstream source.
-
-Whenever a new commit is pushed into GitHub's project branch, a new wrap is generated
-with an incremented version number. All the old releases remain unaltered.
-New commits are always done via GitHub merge requests and must be reviewed by
-someone other than the submitter.
-
-Note that your Git repo with wrap must not contain the subdirectory of the source
-release. That gets added automatically by the service. You also must not commit
-any source code from the original tarball into the wrap repository.
+Each wrap repository has a master branch with only one initial commit
+and *no* wrap files. And that is the only commit ever made on that
+branch.
+
+For every release of a project a new branch is created. The new branch
+is named after the the upstream release number (e.g. `1.0.0`). This
+branch holds a wrap file for this particular release.
+
+There are two types of wraps on WrapDB - regular wraps and wraps with
+Meson build definition patches. A wrap file in a repository on WrapDB
+must have a name `upstream.wrap`.
+
+Wraps with Meson build definition patches work in much the same way as
+Debian: we take the unaltered upstream source package and add a new
+build system to it as a patch. These build systems are stored as Git
+repositories on GitHub. They only contain build definition files. You
+may also think of them as an overlay to upstream source.
+
+Whenever a new commit is pushed into GitHub's project branch, a new
+wrap is generated with an incremented version number. All the old
+releases remain unaltered. New commits are always done via GitHub
+merge requests and must be reviewed by someone other than the
+submitter.
+
+Note that your Git repo with wrap must not contain the subdirectory of
+the source release. That gets added automatically by the service. You
+also must not commit any source code from the original tarball into
+the wrap repository.
## Choosing the repository name
@@ -34,29 +39,32 @@ they should have the same name as the upstream projects.
NOTE: Repo names must fully match this regexp: `[a-z0-9._]+`.
-If the project provides a pkg-config file, then the repository name should be
-the same as the pkg-config name. Usually this is the name of the
-project, such as `libpng`. Sometimes it is slightly different,
+If the project provides a pkg-config file, then the repository name
+should be the same as the pkg-config name. Usually this is the name of
+the project, such as `libpng`. Sometimes it is slightly different,
however. As an example the libogg project's chosen pkg-config name is
`ogg` instead of `libogg`, which is the reason why the repository is
named plain `ogg`.
-If there is no a pkg-config file, the name the project uses/promotes should be used,
-lowercase only (Catch2 -> catch2).
+If there is no a pkg-config file, the name the project uses/promotes
+should be used, lowercase only (Catch2 -> catch2).
If the project name is too generic or ambiguous (e.g. `benchmark`),
-consider using `organization-project` naming format (e.g. `google-benchmark`).
+consider using `organization-project` naming format (e.g.
+`google-benchmark`).
## How to contribute a new wrap
-If the project already uses Meson build system, then only a wrap file - `upstream.wrap`
-should be provided. In other case a Meson build definition patch - a set of `meson.build`
-files - should be also provided.
+If the project already uses Meson build system, then only a wrap file
+- `upstream.wrap` should be provided. In other case a Meson build
+definition patch - a set of `meson.build` files - should be also
+provided.
### Request a new repository
-Create an issue on the [wrapdb bug tracker](https://github.com/mesonbuild/wrapdb/issues)
-using *Title* and *Description* below as a template.
+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>`
@@ -66,17 +74,18 @@ upstream url: <link_to_updastream>
version: <version_you_have_a_wrap_for>
```
-Wait until the new repository or branch is created. A link to the new repository or branch
-will be posted in a comment to this issue.
+Wait until the new repository or branch is created. A link to the new
+repository or branch will be posted in a comment to this issue.
-NOTE: Requesting a branch is not necessary. WrapDB maintainer can create the branch and
-modify the PR accordingly if the project repository exists.
+NOTE: Requesting a branch is not necessary. WrapDB maintainer can
+create the branch and modify the PR accordingly if the project
+repository exists.
### Creating the wrap contents
-Setting up the contents might seem a bit counterintuitive at
-first. Just remember that the outcome needs to have one (and only one)
-commit that has all the build definition files (i.e. `meson.build` and
+Setting up the contents might seem a bit counterintuitive at first.
+Just remember that the outcome needs to have one (and only one) commit
+that has all the build definition files (i.e. `meson.build` and
`meson_options.txt` files) and _nothing else_. It is good practice to
have this commit in a branch whose name matches the release as
described above.
@@ -132,6 +141,25 @@ Under macOS the command is the following:
shasum -a 256 path/to/libfoo-1.0.0.tar.gz
```
+Next you need to add the entries that define what dependencies the
+current project provides. This is important, as it is what makes
+Meson's automatic dependency resolver work. It is done by adding a
+`provide` entry at the end of the `upstream.wrap` file. Using the Ogg
+library as an example, this is what it would look like:
+
+```ini
+[provide]
+ogg = ogg_dep
+```
+
+The `ogg` part on the left refers to the dependency name, which should
+be the same as its Pkg-Config name. `ogg_dep` on the right refers to
+the variable in the build definitions that provides the dependency.
+Most commonly it holds the result of a `declare_dependency` call. If a
+variable of that name is not defined, Meson will exit with a hard
+error. For further details see [the main Wrap
+manual](Wrap-dependency-system-manual.md).
+
Now you can create the build files and work on them until the project
builds correctly.
diff --git a/docs/markdown/Getting-meson.md b/docs/markdown/Getting-meson.md
index e0e5722..3568dfc 100644
--- a/docs/markdown/Getting-meson.md
+++ b/docs/markdown/Getting-meson.md
@@ -23,12 +23,17 @@ a pull-request process that runs CI and tests several platforms.
## Installing Meson with pip
Meson is available in the [Python Package Index] and can be installed with
-`pip3 install meson` which requires root and will install it system-wide.
+`sudo pip3 install meson` which requires root and will install it system-wide.
+
+If you have downloaded a copy of the meson sources already, you can install it
+with `sudo pip3 install path/to/source/root/`.
Alternatively, you can use `pip3 install --user meson` which will install it
for your user and does not require any special privileges. This will install
the package in `~/.local/`, so you will have to add `~/.local/bin` to your
-`PATH`.
+`PATH`, and `sudo meson install` will be completely broken since the
+program will not be available to root. Only use a user copy of meson if you
+do not care about installing projects as root.
## Installing Meson and Ninja with the MSI installer
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 3af78ef..aeaeccb 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -2409,6 +2409,12 @@ page](Configuration.md) It has three methods:
- `has(varname)`: returns `true` if the specified variable is set
+- `keys()`*(since 0.57.0)*: returns an array of keys of
+ the configuration data object.
+
+ You can iterate over this array with the [`foreach`
+ statement](Syntax.md#foreach-statements).
+
- `merge_from(other)` *(since 0.42.0)*: takes as argument a different
configuration data object and copies all entries from that object to
the current.
diff --git a/docs/markdown/Tutorial.md b/docs/markdown/Tutorial.md
index bf337ba..85e345a 100644
--- a/docs/markdown/Tutorial.md
+++ b/docs/markdown/Tutorial.md
@@ -29,8 +29,11 @@ example. First we create a file `main.c` which holds the source. It
looks like this.
```c
-#include<stdio.h>
+#include <stdio.h>
+//
+// main is where all program execution starts
+//
int main(int argc, char **argv) {
printf("Hello there.\n");
return 0;
@@ -53,7 +56,7 @@ to initialize the build by going into the source directory and issuing
the following commands.
```console
-$ meson builddir
+$ meson setup builddir
```
We create a separate build directory to hold all of the compiler
@@ -110,17 +113,40 @@ create a graphical window instead. We'll use the
use GTK+. The new version looks like this.
```c
-#include<gtk/gtk.h>
-int main(int argc, char **argv) {
- GtkWidget *win;
- gtk_init(&argc, &argv);
- win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(win), "Hello there");
- g_signal_connect(win, "destroy", G_CALLBACK(gtk_main_quit), NULL);
- gtk_widget_show(win);
- gtk_main();
-}
+#include <gtk/gtk.h>
+
+//
+// Should provided the active view for a GTK application
+//
+static void activate(GtkApplication* app, gpointer user_data)
+{
+ GtkWidget *window;
+ GtkWidget *label;
+
+ window = gtk_application_window_new (app);
+ label = gtk_label_new("Hello GNOME!");
+ gtk_container_add (GTK_CONTAINER (window), label);
+ gtk_window_set_title(GTK_WINDOW (window), "Welcome to GNOME");
+ gtk_window_set_default_size(GTK_WINDOW (window), 200, 100);
+ gtk_widget_show_all(window);
+} // end of function activate
+
+//
+// main is where all program execution starts
+//
+int main(int argc, char **argv)
+{
+ GtkApplication *app;
+ int status;
+
+ app = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
+ g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
+ status = g_application_run(G_APPLICATION(app), argc, argv);
+ g_object_unref(app);
+
+ return status;
+} // end of function main
```
Then we edit the Meson file, instructing it to find and use the GTK+
diff --git a/docs/markdown/snippets/keys_of_configuration_data.md b/docs/markdown/snippets/keys_of_configuration_data.md
new file mode 100644
index 0000000..c0cbfc2
--- /dev/null
+++ b/docs/markdown/snippets/keys_of_configuration_data.md
@@ -0,0 +1,4 @@
+## Get keys of configuration data object
+
+All keys of the `configuration_data` object can be obtained with the `keys()`
+method as an alphabetically sorted array.
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 09f06da..15218c1 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -266,7 +266,7 @@ class NinjaRule:
# expand variables in command
command = ' '.join([self._quoter(x) for x in self.command + self.args])
estimate = len(command)
- for m in re.finditer(r'(\${\w*}|\$\w*)?[^$]*', command):
+ for m in re.finditer(r'(\${\w+}|\$\w+)?[^$]*', command):
if m.start(1) != -1:
estimate -= m.end(1) - m.start(1) + 1
chunk = m.group(1)
@@ -359,9 +359,9 @@ class NinjaBuildElement:
rulename = self.rulename
line = 'build {}{}: {} {}'.format(outs, implicit_outs, rulename, ins)
if len(self.deps) > 0:
- line += ' | ' + ' '.join([ninja_quote(x, True) for x in self.deps])
+ line += ' | ' + ' '.join([ninja_quote(x, True) for x in sorted(self.deps)])
if len(self.orderdeps) > 0:
- line += ' || ' + ' '.join([ninja_quote(x, True) for x in self.orderdeps])
+ line += ' || ' + ' '.join([ninja_quote(x, True) for x in sorted(self.orderdeps)])
line += '\n'
# This is the only way I could find to make this work on all
# platforms including Windows command shell. Slash is a dir separator
@@ -1489,11 +1489,15 @@ int dummy;
self.create_target_source_introspection(target, valac, args, all_files, [])
return other_src[0], other_src[1], vala_c_src
- def generate_rust_target(self, target):
+ def generate_rust_target(self, target: build.BuildTarget) -> None:
rustc = target.compilers['rust']
# Rust compiler takes only the main file as input and
# figures out what other files are needed via import
# statements and magic.
+ base_proxy = self.get_base_options_for_target(target)
+ args = rustc.compiler_args()
+ # Compiler args for compiling this target
+ args += compilers.get_base_compile_args(base_proxy, rustc)
main_rust_file = None
for i in target.get_sources():
if not rustc.can_compile(i):
@@ -1503,7 +1507,6 @@ int dummy;
if main_rust_file is None:
raise RuntimeError('A Rust target has no Rust sources. This is weird. Also a bug. Please report')
target_name = os.path.join(target.subdir, target.get_filename())
- args = ['--crate-type']
if isinstance(target, build.Executable):
cratetype = 'bin'
elif hasattr(target, 'rust_crate_type'):
@@ -1514,7 +1517,7 @@ int dummy;
cratetype = 'rlib'
else:
raise InvalidArguments('Unknown target type for rustc.')
- args.append(cratetype)
+ args.extend(['--crate-type', cratetype])
# If we're dynamically linking, add those arguments
#
@@ -1536,7 +1539,8 @@ int dummy;
depfile = os.path.join(target.subdir, target.name + '.d')
args += ['--emit', 'dep-info={}'.format(depfile), '--emit', 'link']
args += target.get_extra_args('rust')
- args += ['-o', os.path.join(target.subdir, target.get_filename())]
+ args += rustc.get_output_args(os.path.join(target.subdir, target.get_filename()))
+ args += self.environment.coredata.get_external_args(target.for_machine, rustc.language)
orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets]
linkdirs = OrderedDict()
for d in target.link_targets:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 78292f2..36d4e19 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1359,11 +1359,12 @@ You probably should put it in link_with instead.''')
for link_target in self.link_targets:
if isinstance(link_target, SharedModule):
if self.environment.machines[self.for_machine].is_darwin():
- raise MesonException('''target links against shared modules.
-This is not permitted on OSX''')
+ raise MesonException(
+ 'target links against shared modules. This is not permitted on OSX')
else:
- mlog.warning('''target links against shared modules. This is not
-recommended as it is not supported on some platforms''')
+ mlog.warning('target links against shared modules. This '
+ 'is not recommended as it is not supported on some '
+ 'platforms')
return
class Generator:
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 95c4698..985f6f3 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2017 The Meson development team
+# Copyright 2012-2020 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -95,28 +95,32 @@ class CCompiler(CLikeCompiler, Compiler):
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
+ def get_options(self) -> 'OptionDictType':
+ opts = super().get_options()
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C langauge standard to use',
+ ['none'],
+ 'none',
+ )
+ })
+ return opts
-class ClangCCompiler(ClangCompiler, CCompiler):
+
+class _ClangCStds(CompilerMixinBase):
+
+ """Mixin class for clang based compilers for setting C standards.
+
+ This is used by both ClangCCompiler and ClangClCompiler, as they share
+ the same versions
+ """
_C17_VERSION = '>=6.0.0'
_C18_VERSION = '>=8.0.0'
_C2X_VERSION = '>=9.0.0'
- def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
- info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
- linker: T.Optional['DynamicLinker'] = None,
- defines: T.Optional[T.Dict[str, str]] = None,
- full_version: T.Optional[str] = None):
- CCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version)
- ClangCompiler.__init__(self, defines)
- default_warn_args = ['-Wall', '-Winvalid-pch']
- self.warn_args = {'0': [],
- '1': default_warn_args,
- '2': default_warn_args + ['-Wextra'],
- '3': default_warn_args + ['-Wextra', '-Wpedantic']}
-
def get_options(self) -> 'OptionDictType':
- opts = CCompiler.get_options(self)
+ opts = super().get_options()
c_stds = ['c89', 'c99', 'c11']
g_stds = ['gnu89', 'gnu99', 'gnu11']
# https://releases.llvm.org/6.0.0/tools/clang/docs/ReleaseNotes.html
@@ -130,13 +134,27 @@ class ClangCCompiler(ClangCompiler, CCompiler):
if version_compare(self.version, self._C2X_VERSION):
c_stds += ['c2x']
g_stds += ['gnu2x']
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- ['none'] + c_stds + g_stds,
- 'none',
- ),
- })
+ opts['std'].choices = ['none'] + c_stds + g_stds # type: ignore
+ return opts
+
+
+class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler):
+
+ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
+ info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
+ linker: T.Optional['DynamicLinker'] = None,
+ defines: T.Optional[T.Dict[str, str]] = None,
+ full_version: T.Optional[str] = None):
+ CCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version)
+ ClangCompiler.__init__(self, defines)
+ default_warn_args = ['-Wall', '-Winvalid-pch']
+ self.warn_args = {'0': [],
+ '1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
+
+ def get_options(self) -> 'OptionDictType':
+ opts = super().get_options()
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
'winlibs': coredata.UserArrayOption(
@@ -207,13 +225,7 @@ class ArmclangCCompiler(ArmclangCompiler, CCompiler):
def get_options(self) -> 'OptionDictType':
opts = CCompiler.get_options(self)
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11'],
- 'none',
- ),
- })
+ opts['std'].choices = ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11'] # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -255,13 +267,7 @@ class GnuCCompiler(GnuCompiler, CCompiler):
if version_compare(self.version, self._C2X_VERSION):
c_stds += ['c2x']
g_stds += ['gnu2x']
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- ['none'] + c_stds + g_stds,
- 'none',
- ),
- })
+ opts['std'].choices = ['none'] + c_stds + g_stds # type: ignore
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
'winlibs': coredata.UserArrayOption(
@@ -327,17 +333,11 @@ class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler):
# It does support some various ISO standards and c/gnu 90, 9x, 1x in addition to those which GNU CC supports.
def get_options(self) -> 'OptionDictType':
opts = CCompiler.get_options(self)
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- [
- 'none', 'c89', 'c90', 'c9x', 'c99', 'c1x', 'c11',
- 'gnu89', 'gnu90', 'gnu9x', 'gnu99', 'gnu1x', 'gnu11',
- 'iso9899:2011', 'iso9899:1990', 'iso9899:199409', 'iso9899:1999',
- ],
- 'none',
- ),
- })
+ opts['std'].choices = [ # type: ignore
+ 'none', 'c89', 'c90', 'c9x', 'c99', 'c1x', 'c11',
+ 'gnu89', 'gnu90', 'gnu9x', 'gnu99', 'gnu1x', 'gnu11',
+ 'iso9899:2011', 'iso9899:1990', 'iso9899:199409', 'iso9899:1999',
+ ]
return opts
# Elbrus C compiler does not have lchmod, but there is only linker warning, not compiler error.
@@ -374,13 +374,7 @@ class IntelCCompiler(IntelGnuLikeCompiler, CCompiler):
g_stds = ['gnu89', 'gnu99']
if version_compare(self.version, '>=16.0.0'):
c_stds += ['c11']
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- ['none'] + c_stds + g_stds,
- 'none',
- ),
- })
+ opts['std'].choices = ['none'] + c_stds + g_stds # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -416,6 +410,9 @@ class VisualStudioLikeCCompilerMixin(CompilerMixinBase):
class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompiler):
+ _C11_VERSION = '>=19.28'
+ _C17_VERSION = '>=19.28'
+
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo', target: str,
exe_wrapper: T.Optional['ExternalProgram'] = None,
@@ -428,26 +425,37 @@ class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompi
def get_options(self) -> 'OptionDictType':
opts = super().get_options()
- c_stds = ['none', 'c89', 'c99', 'c11']
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- c_stds,
- 'none',
- ),
- })
+ c_stds = ['c89', 'c99']
+ # Need to have these to be compatible with projects
+ # that set c_std to e.g. gnu99.
+ # https://github.com/mesonbuild/meson/issues/7611
+ g_stds = ['gnu89', 'gnu90', 'gnu9x', 'gnu99']
+ if version_compare(self.version, self._C11_VERSION):
+ c_stds += ['c11']
+ g_stds += ['gnu1x', 'gnu11']
+ if version_compare(self.version, self._C17_VERSION):
+ c_stds += ['c17', 'c18']
+ g_stds += ['gnu17', 'gnu18']
+ opts['std'].choices = ['none'] + c_stds + g_stds # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
args = []
std = options['std']
- # As of MVSC 16.7, /std:c11 is the only valid C standard option.
- if std.value in {'c11'}:
- args.append('/std:' + std.value)
+ if std.value.startswith('gnu'):
+ mlog.log_once(
+ 'cl.exe does not actually support gnu standards, and meson '
+ 'will instead demote to the nearest ISO C standard. This '
+ 'may cause compilation to fail.')
+ # As of MVSC 16.8, /std:c11 and /std:c17 are the only valid C standard options.
+ if std.value in {'c11', 'gnu1x', 'gnu11'}:
+ args.append('/std:c11')
+ elif std.value in {'c17', 'c18', 'gnu17', 'gnu18'}:
+ args.append('/std:c17')
return args
-class ClangClCCompiler(ClangClCompiler, VisualStudioLikeCCompilerMixin, CCompiler):
+class ClangClCCompiler(_ClangCStds, ClangClCompiler, VisualStudioLikeCCompilerMixin, CCompiler):
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo', target: str,
exe_wrapper: T.Optional['ExternalProgram'] = None,
@@ -458,6 +466,12 @@ class ClangClCCompiler(ClangClCompiler, VisualStudioLikeCCompilerMixin, CCompile
full_version=full_version)
ClangClCompiler.__init__(self, target)
+ def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ std = options['std'].value
+ if std != "none":
+ return ['/clang:-std={}'.format(std)]
+ return []
+
class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler):
@@ -475,21 +489,14 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM
def get_options(self) -> 'OptionDictType':
opts = super().get_options()
- c_stds = ['none', 'c89', 'c99', 'c11']
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- c_stds,
- 'none',
- ),
- })
+ opts['std'].choices = ['none', 'c89', 'c99', 'c11'] # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
args = []
std = options['std']
if std.value == 'c89':
- mlog.warning("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.", once=True)
+ mlog.log_once("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.")
elif std.value != 'none':
args.append('/Qstd:' + std.value)
return args
@@ -508,13 +515,7 @@ class ArmCCompiler(ArmCompiler, CCompiler):
def get_options(self) -> 'OptionDictType':
opts = CCompiler.get_options(self)
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- ['none', 'c90', 'c99'],
- 'none',
- ),
- })
+ opts['std'].choices = ['none', 'c89', 'c99', 'c11'] # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -541,13 +542,7 @@ class CcrxCCompiler(CcrxCompiler, CCompiler):
def get_options(self) -> 'OptionDictType':
opts = CCompiler.get_options(self)
- opts.update({
- 'std': coredata.UserComboOption(
- 'C language standard to use',
- ['none', 'c89', 'c99'],
- 'none',
- ),
- })
+ opts['std'].choices = ['none', 'c89', 'c99'] # type: ignore
return opts
def get_no_stdinc_args(self) -> T.List[str]:
@@ -592,9 +587,7 @@ class Xc16CCompiler(Xc16Compiler, CCompiler):
def get_options(self) -> 'OptionDictType':
opts = CCompiler.get_options(self)
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none', 'c89', 'c99', 'gnu89', 'gnu99'],
- 'none')})
+ opts['std'].choices = ['none', 'c89', 'c99', 'gnu89', 'gnu99'] # type: ignore
return opts
def get_no_stdinc_args(self) -> T.List[str]:
@@ -637,9 +630,7 @@ class CompCertCCompiler(CompCertCompiler, CCompiler):
def get_options(self) -> 'OptionDictType':
opts = CCompiler.get_options(self)
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none', 'c89', 'c99'],
- 'none')})
+ opts['std'].choices = ['none', 'c89', 'c99'] # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -675,9 +666,7 @@ class C2000CCompiler(C2000Compiler, CCompiler):
def get_options(self) -> 'OptionDictType':
opts = CCompiler.get_options(self)
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none', 'c89', 'c99', 'c11'],
- 'none')})
+ opts['std'].choices = ['none', 'c89', 'c99', 'c11'] # type: ignore
return opts
def get_no_stdinc_args(self) -> T.List[str]:
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 0f074bb..4e9b86b 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -785,7 +785,7 @@ class Compiler(metaclass=abc.ABCMeta):
# On Windows antivirus programs and the like hold on to files so
# they can't be deleted. There's not much to do in this case. Also,
# catch OSError because the directory is then no longer empty.
- yield None
+ return
@contextlib.contextmanager
def cached_compile(self, code: str, cdata: coredata.CoreData, *,
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 3e9764a..6ba87eb 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -167,6 +167,17 @@ class CPPCompiler(CLikeCompiler, Compiler):
raise MesonException('C++ Compiler does not support -std={}'.format(cpp_std))
+ def get_options(self) -> 'OptionDictType':
+ opts = super().get_options()
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ ['none'],
+ 'none',
+ ),
+ })
+ return opts
+
class ClangCPPCompiler(ClangCompiler, CPPCompiler):
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
@@ -192,13 +203,11 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
'default',
),
'rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'std': coredata.UserComboOption(
- 'C++ language standard to use',
- ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
- 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
- 'none',
- ),
})
+ opts['std'].choices = [ # type: ignore
+ 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z',
+ 'c++2a', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a',
+ ]
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
'winlibs': coredata.UserArrayOption(
@@ -283,15 +292,11 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
['none', 'default', 'a', 's', 'sc'],
'default',
),
- 'std': coredata.UserComboOption(
- 'C++ language standard to use',
- [
- 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17',
- 'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17',
- ],
- 'none',
- ),
})
+ opts['std'].choices = [ # type: ignore
+ 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'gnu++98',
+ 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17',
+ ]
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -332,17 +337,16 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
'default',
),
'rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'std': coredata.UserComboOption(
- 'C++ language standard to use',
- ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
- 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
- 'none',
- ),
'debugstl': coredata.UserBooleanOption(
'STL debug mode',
False,
)
})
+ opts['std'].choices = [ # type: ignore
+ 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z',
+ 'c++2a', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z',
+ 'gnu++2a',
+ ]
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
'winlibs': coredata.UserArrayOption(
@@ -437,16 +441,12 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
['none', 'default', 'a', 's', 'sc'],
'default',
),
- 'std': coredata.UserComboOption(
- 'C++ language standard to use',
- cpp_stds,
- 'none',
- ),
'debugstl': coredata.UserBooleanOption(
'STL debug mode',
False,
),
})
+ opts['std'].choices = cpp_stds # type: ignore
return opts
# Elbrus C++ compiler does not have lchmod, but there is only linker warning, not compiler error.
@@ -515,13 +515,9 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
'default',
),
'rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'std': coredata.UserComboOption(
- 'C++ language standard to use',
- ['none'] + c_stds + g_stds,
- 'none',
- ),
'debugstl': coredata.UserBooleanOption('STL debug mode', False),
})
+ opts['std'].choices = ['none'] + c_stds + g_stds # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -573,16 +569,12 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase):
'default',
),
'rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'std': coredata.UserComboOption(
- 'C++ language standard to use',
- cpp_stds,
- 'none',
- ),
'winlibs': coredata.UserArrayOption(
'Windows libs to link against.',
msvc_winlibs,
),
})
+ opts['std'].choices = cpp_stds # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -726,13 +718,7 @@ class ArmCPPCompiler(ArmCompiler, CPPCompiler):
def get_options(self) -> 'OptionDictType':
opts = CPPCompiler.get_options(self)
- opts.update({
- 'std': coredata.UserComboOption(
- 'C++ language standard to use',
- ['none', 'c++03', 'c++11'],
- 'none',
- ),
- })
+ opts['std'].choices = ['none', 'c++03', 'c++11'] # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -790,9 +776,7 @@ class C2000CPPCompiler(C2000Compiler, CPPCompiler):
def get_options(self) -> 'OptionDictType':
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_std': coredata.UserComboOption('C++ language standard to use',
- ['none', 'c++03'],
- 'none')})
+ opts['std'].choices = ['none', 'c++03'] # type: ignore
return opts
def get_always_args(self) -> T.List[str]:
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 603ad13..89fcf40 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -197,9 +197,9 @@ class CudaCompiler(Compiler):
def get_options(self) -> 'OptionDictType':
opts = super().get_options()
- opts.update({'cuda_std': coredata.UserComboOption('C++ language standard to use',
- ['none', 'c++03', 'c++11', 'c++14'],
- 'none')})
+ opts.update({'std': coredata.UserComboOption('C++ language standard to use with cuda',
+ ['none', 'c++03', 'c++11', 'c++14'],
+ 'none')})
return opts
def _to_host_compiler_options(self, options: 'OptionDictType') -> 'OptionDictType':
@@ -212,7 +212,7 @@ class CudaCompiler(Compiler):
# the combination of CUDA version and MSVC version; the --std= is thus ignored
# and attempting to use it will result in a warning: https://stackoverflow.com/a/51272091/741027
if not is_windows():
- std = options['cuda_std']
+ std = options['std']
if std.value != 'none':
args.append('--std=' + std.value)
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index e85ee6d..036369a 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -150,6 +150,17 @@ class FortranCompiler(CLikeCompiler, Compiler):
def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
return self._has_multi_link_arguments(args, env, 'stop; end program')
+ def get_options(self) -> 'OptionDictType':
+ opts = super().get_options()
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'Fortran language standard to use',
+ ['none'],
+ 'none',
+ ),
+ })
+ return opts
+
class GnuFortranCompiler(GnuCompiler, FortranCompiler):
@@ -175,13 +186,7 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
fortran_stds += ['f2008']
if version_compare(self.version, '>=8.0.0'):
fortran_stds += ['f2018']
- opts.update({
- 'std': coredata.UserComboOption(
- 'Fortran language standard to use',
- ['none'] + fortran_stds,
- 'none',
- ),
- })
+ opts['std'].choices = ['none'] + fortran_stds # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -310,14 +315,7 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
def get_options(self) -> 'OptionDictType':
opts = FortranCompiler.get_options(self)
- fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018']
- opts.update({
- 'std': coredata.UserComboOption(
- 'Fortran language standard to use',
- ['none'] + fortran_stds,
- 'none',
- ),
- })
+ opts['std'].choices = ['legacy', 'f95', 'f2003', 'f2008', 'f2018'] # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
@@ -367,14 +365,7 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
def get_options(self) -> 'OptionDictType':
opts = FortranCompiler.get_options(self)
- fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018']
- opts.update({
- 'std': coredata.UserComboOption(
- 'Fortran language standard to use',
- ['none'] + fortran_stds,
- 'none',
- ),
- })
+ opts['std'].choices = ['legacy', 'f95', 'f2003', 'f2008', 'f2018'] # type: ignore
return opts
def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py
index 87bc40c..cd18b35 100644
--- a/mesonbuild/compilers/mixins/emscripten.py
+++ b/mesonbuild/compilers/mixins/emscripten.py
@@ -50,7 +50,7 @@ class EmscriptenMixin(Compiler):
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-s', 'USE_PTHREADS=1']
- count = env.coredata.compiler_options[self.for_machine]['{}_thread_count'.format(self.language)].value # type: int
+ count = env.coredata.compiler_options[self.for_machine][self.language]['thread_count'].value # type: int
if count:
args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)])
return args
@@ -58,7 +58,7 @@ class EmscriptenMixin(Compiler):
def get_options(self) -> 'coredata.OptionDictType':
opts = super().get_options()
opts.update({
- '{}_thread_count'.format(self.language): coredata.UserIntegerOption(
+ 'thread_count': coredata.UserIntegerOption(
'Number of threads to use in web assembly, set to 0 to disable',
(0, None, 4), # Default was picked at random
),
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index 469859b..312b3b6 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -17,7 +17,7 @@ import textwrap
import typing as T
from .. import coredata
-from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
+from ..mesonlib import EnvironmentException, MachineChoice, MesonException, Popen_safe
from .compilers import Compiler, rust_buildtype_args, clike_debug_args
if T.TYPE_CHECKING:
@@ -52,6 +52,9 @@ class RustCompiler(Compiler):
linker=linker)
self.exe_wrapper = exe_wrapper
self.id = 'rustc'
+ self.base_options.append('b_colorout')
+ if 'link' in self.linker.id:
+ self.base_options.append('b_vscrt')
def needs_static_linker(self) -> bool:
return False
@@ -122,6 +125,10 @@ class RustCompiler(Compiler):
def get_output_args(self, outputname: str) -> T.List[str]:
return ['-o', outputname]
+ @classmethod
+ def use_linker_args(cls, linker: str) -> T.List[str]:
+ return ['-C', 'linker={}'.format(linker)]
+
# Rust does not have a use_linker_args because it dispatches to a gcc-like
# C compiler for dynamic linking, as such we invoke the C compiler's
# use_linker_args method instead.
@@ -141,3 +148,12 @@ class RustCompiler(Compiler):
if std.value != 'none':
args.append('--edition=' + std.value)
return args
+
+ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+ # Rust handles this for us, we don't need to do anything
+ return []
+
+ def get_colorout_args(self, colortype: str) -> T.List[str]:
+ if colortype in {'always', 'never', 'auto'}:
+ return [f'--color={colortype}']
+ raise MesonException(f'Invalid color type for rust {colortype}')
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 3a5f5f8..87518e1 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -869,9 +869,13 @@ class PkgConfigDependency(ExternalDependency):
def _set_libs(self):
env = None
- libcmd = [self.name, '--libs']
+ libcmd = ['--libs']
+
if self.static:
libcmd.append('--static')
+
+ libcmd.append(self.name)
+
# Force pkg-config to output -L fields even if they are system
# paths so we can do manual searching with cc.find_library() later.
env = os.environ.copy()
diff --git a/mesonbuild/depfile.py b/mesonbuild/depfile.py
index 7a896cd..62cbe81 100644
--- a/mesonbuild/depfile.py
+++ b/mesonbuild/depfile.py
@@ -82,4 +82,4 @@ class DepFile:
deps.update(target.deps)
for dep in target.deps:
deps.update(self.get_all_dependencies(dep, visited))
- return deps
+ return sorted(deps)
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 588005b..7194d03 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -129,6 +129,9 @@ from .compilers import (
VisualStudioCPPCompiler,
)
+if T.TYPE_CHECKING:
+ from .dependencies import ExternalProgram
+
build_filename = 'meson.build'
CompilersDict = T.Dict[str, Compiler]
@@ -869,7 +872,7 @@ class Environment:
defines[rest[0]] = rest[1]
return defines
- def _get_compilers(self, lang, for_machine):
+ def _get_compilers(self, lang: str, for_machine: MachineChoice) -> T.Tuple[T.List[T.List[str]], T.List[str], T.Optional['ExternalProgram']]:
'''
The list of compilers is detected in the exact same way for
C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here.
@@ -1062,9 +1065,17 @@ class Environment:
self.__failed_to_detect_linker(compiler, check_args, o, e)
return linker
- def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice) -> Compiler:
+ def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice, *, override_compiler: T.Optional[T.List[str]] = None) -> Compiler:
+ """Shared implementation for finding the C or C++ compiler to use.
+
+ the override_compiler option is provided to allow compilers which use
+ the compiler (GCC or Clang usually) as their shared linker, to find
+ the linker they need.
+ """
popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine)
+ if override_compiler is not None:
+ compilers = [override_compiler]
is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
@@ -1619,9 +1630,9 @@ class Environment:
return comp_class(exelist, version, for_machine, info, is_cross)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
- def detect_rust_compiler(self, for_machine):
- popen_exceptions = {}
- compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine)
+ def detect_rust_compiler(self, for_machine: MachineChoice) -> RustCompiler:
+ popen_exceptions = {} # type: T.Dict[str, Exception]
+ compilers, _, exe_wrap = self._get_compilers('rust', for_machine)
is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine]
@@ -1634,7 +1645,7 @@ class Environment:
compiler = [compiler]
arg = ['--version']
try:
- p, out = Popen_safe(compiler + arg)[0:2]
+ out = Popen_safe(compiler + arg)[1]
except OSError as e:
popen_exceptions[' '.join(compiler + arg)] = e
continue
@@ -1651,17 +1662,30 @@ class Environment:
# the default use that, and second add the necessary arguments
# to rust to use -fuse-ld
+ if any(a.startswith('linker=') for a in compiler):
+ mlog.warning(
+ 'Please do not put -C linker= in your compiler '
+ 'command, set rust_ld=command in your cross file '
+ 'or use the RUST_LD environment variable. meson '
+ 'will override your seletion otherwise.')
+
if override is None:
extra_args = {}
always_args = []
if is_link_exe:
- compiler.extend(['-C', 'linker={}'.format(cc.linker.exelist[0])])
+ compiler.extend(RustCompiler.use_linker_args(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)])
+ else:
+ exelist = cc.linker.exelist.copy()
+ if 'ccache' in exelist[0]:
+ del exelist[0]
+ c = exelist.pop(0)
+ compiler.extend(RustCompiler.use_linker_args(c))
+
+ # Also ensure that we pass any extra arguments to the linker
+ for l in exelist:
+ compiler.extend(['-C', 'link-arg={}'.format(l)])
# This trickery with type() gets us the class of the linker
# so we can initialize a new copy for the Rust Compiler
@@ -1675,21 +1699,22 @@ class Environment:
elif 'link' in override[0]:
linker = self._guess_win_linker(
override, RustCompiler, for_machine, use_linker_prefix=False)
+ # rustc takes linker arguments without a prefix, and
+ # inserts the correct prefix itself.
linker.direct = True
+ compiler.extend(RustCompiler.use_linker_args(linker.exelist[0]))
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)
+ # On linux and macos rust will invoke the c compiler for
+ # linking, on windows it will use lld-link or link.exe.
+ # we will simply ask for the C compiler that coresponds to
+ # it, and use that.
+ cc = self._detect_c_or_cpp_compiler('c', for_machine, override_compiler=override)
+ linker = cc.linker
# 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])))])
+ c = linker.exelist[1] if linker.exelist[0].endswith('ccache') else linker.exelist[0]
+ compiler.extend(RustCompiler.use_linker_args(c))
self.coredata.add_lang_args(RustCompiler.language, RustCompiler, for_machine, self)
return RustCompiler(
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 28ac74f..6896a4d 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -308,6 +308,7 @@ class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
'set_quoted': self.set_quoted_method,
'has': self.has_method,
'get': self.get_method,
+ 'keys': self.keys_method,
'get_unquoted': self.get_unquoted_method,
'merge_from': self.merge_from_method,
})
@@ -401,6 +402,10 @@ class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
def get(self, name):
return self.held_object.values[name] # (val, desc)
+ @FeatureNew('configuration_data.keys()', '0.57.0')
+ def keys_method(self, args, kwargs):
+ return sorted(self.keys())
+
def keys(self):
return self.held_object.values.keys()
@@ -3170,6 +3175,8 @@ external dependencies (including libraries) must go to "dependencies".''')
self.build.project_name = proj_name
self.active_projectname = proj_name
self.project_version = kwargs.get('version', 'undefined')
+ if not isinstance(self.project_version, str):
+ raise InvalidCode('The version keyword argument must be a string.')
if self.build.project_version is None:
self.build.project_version = self.project_version
proj_license = mesonlib.stringlistify(kwargs.get('license', 'unknown'))
@@ -4636,7 +4643,11 @@ different subdirectory.
self.add_project_arguments(node, self.build.projects_link_args[for_machine], args, kwargs)
def warn_about_builtin_args(self, args):
- warnargs = ('/W1', '/W2', '/W3', '/W4', '/Wall', '-Wall', '-Wextra', '-Wpedantic')
+ # -Wpedantic is deliberately not included, since some people want to use it but not use -Wextra
+ # see e.g.
+ # https://github.com/mesonbuild/meson/issues/3275#issuecomment-641354956
+ # https://github.com/mesonbuild/meson/issues/3742
+ warnargs = ('/W1', '/W2', '/W3', '/W4', '/Wall', '-Wall', '-Wextra')
optargs = ('-O0', '-O2', '-O3', '-Os', '/O1', '/O2', '/Os')
for arg in args:
if arg in warnargs:
@@ -4645,6 +4656,9 @@ different subdirectory.
elif arg in optargs:
mlog.warning('Consider using the built-in optimization level instead of using "{}".'.format(arg),
location=self.current_node)
+ elif arg == '-Werror':
+ mlog.warning('Consider using the built-in werror option instead of using "{}".'.format(arg),
+ location=self.current_node)
elif arg == '-g':
mlog.warning('Consider using the built-in debug option instead of using "{}".'.format(arg),
location=self.current_node)
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index d3f8181..e57580b 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -823,7 +823,7 @@ The result of this is undefined and will become a hard error in a future Meson r
elif isinstance(items, dict):
if len(node.varnames) != 2:
raise InvalidArguments('Foreach on dict unpacks key and value')
- for key, value in items.items():
+ for key, value in sorted(items.items()):
self.set_variable(node.varnames[0], key)
self.set_variable(node.varnames[1], value)
try:
@@ -1166,7 +1166,7 @@ The result of this is undefined and will become a hard error in a future Meson r
if method_name == 'keys':
if len(posargs) != 0:
raise InterpreterException('keys() takes no arguments.')
- return list(obj.keys())
+ return sorted(obj.keys())
raise InterpreterException('Dictionaries do not have a method called "%s".' % method_name)
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index eefb308..46e2de1 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -124,7 +124,7 @@ class AnsiDecorator:
def get_text(self, with_codes: bool) -> str:
text = self.text
- if with_codes:
+ if with_codes and self.code:
text = self.code + self.text + AnsiDecorator.plain_code
if self.quoted:
text = '"{}"'.format(text)
@@ -133,6 +133,9 @@ class AnsiDecorator:
def bold(text: str, quoted: bool = False) -> AnsiDecorator:
return AnsiDecorator(text, "\033[1m", quoted=quoted)
+def plain(text: str) -> AnsiDecorator:
+ return AnsiDecorator(text, "")
+
def red(text: str) -> AnsiDecorator:
return AnsiDecorator(text, "\033[1;31m")
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 2d32328..547aff1 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -554,15 +554,16 @@ class GnomeModule(ExtensionModule):
else:
# Because of https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/72
# we can't use the full path until this is merged.
+ libpath = os.path.join(girtarget.get_subdir(), girtarget.get_filename())
if isinstance(girtarget, build.SharedLibrary):
+ # need to put our output directory first as we need to use the
+ # generated libraries instead of any possibly installed system/prefix
+ # ones.
+ ret += ["-L@BUILD_ROOT@/{}".format(os.path.dirname(libpath))]
libname = girtarget.get_basename()
else:
- libname = os.path.join("@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id(), girtarget.get_filename())
+ libname = os.path.join("@BUILD_ROOT@/{}".format(libpath))
ret += ['--library', libname]
- # need to put our output directory first as we need to use the
- # generated libraries instead of any possibly installed system/prefix
- # ones.
- ret += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()]
# Needed for the following binutils bug:
# https://github.com/mesonbuild/meson/issues/1911
# However, g-ir-scanner does not understand -Wl,-rpath
@@ -1429,7 +1430,7 @@ class GnomeModule(ExtensionModule):
GType
%s@enum_name@_get_type (void)
{
- static volatile gsize gtype_id = 0;
+ static gsize gtype_id = 0;
static const G@Type@Value values[] = {''' % func_prefix
c_file_kwargs['vprod'] = ' { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },'
diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py
index e23e12e..e49a548 100644
--- a/mesonbuild/modules/sourceset.py
+++ b/mesonbuild/modules/sourceset.py
@@ -14,7 +14,7 @@
from collections import namedtuple
from .. import mesonlib
-from ..mesonlib import listify
+from ..mesonlib import listify, OrderedSet
from . import ExtensionModule
from ..interpreterbase import (
noPosargs, noKwargs, permittedKwargs,
@@ -111,7 +111,7 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder):
def collect(self, enabled_fn, all_sources, into=None):
if not into:
- into = SourceFiles(set(), set())
+ into = SourceFiles(OrderedSet(), OrderedSet())
for entry in self.held_object:
if all(x.found() for x in entry.dependencies) and \
all(enabled_fn(key) for key in entry.keys):
diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py
index fc8c033..95e6b79 100644
--- a/mesonbuild/msetup.py
+++ b/mesonbuild/msetup.py
@@ -181,7 +181,7 @@ class MesonApp:
else:
logger_fun = mlog.debug
build_machine = intr.builtin['build_machine']
- host_machine = intr.builtin['build_machine']
+ host_machine = intr.builtin['host_machine']
target_machine = intr.builtin['target_machine']
assert isinstance(build_machine, interpreter.MachineHolder)
assert isinstance(host_machine, interpreter.MachineHolder)
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 35cb10a..5804303 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -15,10 +15,10 @@
# A tool to run tests in many different ways.
from ._pathlib import Path
-from collections import namedtuple
+from collections import deque, namedtuple
from copy import deepcopy
import argparse
-import concurrent.futures as conc
+import asyncio
import datetime
import enum
import io
@@ -167,6 +167,7 @@ class TestResult(enum.Enum):
OK = 'OK'
TIMEOUT = 'TIMEOUT'
+ INTERRUPT = 'INTERRUPT'
SKIP = 'SKIP'
FAIL = 'FAIL'
EXPECTEDFAIL = 'EXPECTEDFAIL'
@@ -326,7 +327,6 @@ class TAPParser:
yield self.Error('Too many tests run (expected {}, got {})'.format(plan.count, num_tests))
-
class JunitBuilder:
"""Builder for Junit test results.
@@ -376,7 +376,8 @@ class JunitBuilder:
'testsuite',
name=suitename,
tests=str(len(test.results)),
- errors=str(sum(1 for r in test.results if r is TestResult.ERROR)),
+ errors=str(sum(1 for r in test.results if r in
+ {TestResult.INTERRUPT, TestResult.ERROR})),
failures=str(sum(1 for r in test.results if r in
{TestResult.FAIL, TestResult.UNEXPECTEDPASS, TestResult.TIMEOUT})),
skipped=str(sum(1 for r in test.results if r is TestResult.SKIP)),
@@ -395,6 +396,9 @@ class JunitBuilder:
elif result is TestResult.UNEXPECTEDPASS:
fail = et.SubElement(testcase, 'failure')
fail.text = 'Test unexpected passed.'
+ elif result is TestResult.INTERRUPT:
+ fail = et.SubElement(testcase, 'failure')
+ fail.text = 'Test was interrupted by user.'
elif result is TestResult.TIMEOUT:
fail = et.SubElement(testcase, 'failure')
fail.text = 'Test did not finish before configured timeout.'
@@ -606,6 +610,31 @@ def load_tests(build_dir: str) -> T.List[TestSerialisation]:
objs = check_testdata(pickle.load(f))
return objs
+# Custom waiting primitives for asyncio
+
+async def try_wait_one(*awaitables: T.Any, timeout: T.Optional[T.Union[int, float]]) -> None:
+ try:
+ await asyncio.wait(awaitables,
+ timeout=timeout, return_when=asyncio.FIRST_COMPLETED)
+ except asyncio.TimeoutError:
+ pass
+
+async def complete(future: asyncio.Future) -> None:
+ """Wait for completion of the given future, ignoring cancellation."""
+ try:
+ await future
+ except asyncio.CancelledError:
+ pass
+
+async def complete_all(futures: T.Iterable[asyncio.Future]) -> None:
+ """Wait for completion of all the given futures, ignoring cancellation."""
+ while futures:
+ done, futures = await asyncio.wait(futures, return_when=asyncio.FIRST_EXCEPTION)
+ # Raise exceptions if needed for all the "done" futures
+ for f in done:
+ if not f.cancelled():
+ f.result()
+
class SingleTestRunner:
@@ -636,7 +665,7 @@ class SingleTestRunner:
return self.test.exe_runner.get_command() + self.test.fname
return self.test.fname
- def run(self) -> TestRun:
+ async def run(self) -> TestRun:
cmd = self._get_cmd()
if cmd is None:
skip_stdout = 'Not run because can not execute cross compiled binaries.'
@@ -645,9 +674,94 @@ class SingleTestRunner:
wrap = TestHarness.get_wrapper(self.options)
if self.options.gdb:
self.test.timeout = None
- return self._run_cmd(wrap + cmd + self.test.cmd_args + self.options.test_args)
+ return await self._run_cmd(wrap + cmd + self.test.cmd_args + self.options.test_args)
+
+ async def _run_subprocess(self, args: T.List[str], *, timeout: T.Optional[int],
+ stdout: T.IO, stderr: T.IO,
+ env: T.Dict[str, str], cwd: T.Optional[str]) -> T.Tuple[int, TestResult, T.Optional[str]]:
+ async def kill_process(p: asyncio.subprocess.Process) -> T.Optional[str]:
+ # Python does not provide multiplatform support for
+ # killing a process and all its children so we need
+ # to roll our own.
+ try:
+ if is_windows():
+ subprocess.run(['taskkill', '/F', '/T', '/PID', str(p.pid)])
+ else:
+ # Send a termination signal to the process group that setsid()
+ # created - giving it a chance to perform any cleanup.
+ os.killpg(p.pid, signal.SIGTERM)
+
+ # Make sure the termination signal actually kills the process
+ # group, otherwise retry with a SIGKILL.
+ await try_wait_one(p.wait(), timeout=0.5)
+ if p.returncode is not None:
+ return None
+
+ os.killpg(p.pid, signal.SIGKILL)
+
+ await try_wait_one(p.wait(), timeout=1)
+ if p.returncode is not None:
+ return None
- def _run_cmd(self, cmd: T.List[str]) -> TestRun:
+ # An earlier kill attempt has not worked for whatever reason.
+ # Try to kill it one last time with a direct call.
+ # If the process has spawned children, they will remain around.
+ p.kill()
+ await try_wait_one(p.wait(), timeout=1)
+ if p.returncode is not None:
+ return None
+ return 'Test process could not be killed.'
+ except ProcessLookupError:
+ # Sometimes (e.g. with Wine) this happens. There's nothing
+ # we can do, probably the process already died so just wait
+ # for the event loop to pick that up.
+ await p.wait()
+ return None
+
+ # Let gdb handle ^C instead of us
+ if self.options.gdb:
+ previous_sigint_handler = signal.getsignal(signal.SIGINT)
+ # Make the meson executable ignore SIGINT while gdb is running.
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+ def preexec_fn() -> None:
+ if self.options.gdb:
+ # Restore the SIGINT handler for the child process to
+ # ensure it can handle it.
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ else:
+ # We don't want setsid() in gdb because gdb needs the
+ # terminal in order to handle ^C and not show tcsetpgrp()
+ # errors avoid not being able to use the terminal.
+ os.setsid()
+
+ p = await asyncio.create_subprocess_exec(*args,
+ stdout=stdout,
+ stderr=stderr,
+ env=env,
+ cwd=cwd,
+ preexec_fn=preexec_fn if not is_windows() else None)
+ result = None
+ additional_error = None
+ try:
+ await try_wait_one(p.wait(), timeout=timeout)
+ if p.returncode is None:
+ if self.options.verbose:
+ print('{} time out (After {} seconds)'.format(self.test.name, timeout))
+ additional_error = await kill_process(p)
+ result = TestResult.TIMEOUT
+ except asyncio.CancelledError:
+ # The main loop must have seen Ctrl-C.
+ additional_error = await kill_process(p)
+ result = TestResult.INTERRUPT
+ finally:
+ if self.options.gdb:
+ # Let us accept ^C again
+ signal.signal(signal.SIGINT, previous_sigint_handler)
+
+ return p.returncode or 0, result, additional_error
+
+ async def _run_cmd(self, cmd: T.List[str]) -> TestRun:
starttime = time.time()
if self.test.extra_paths:
@@ -678,23 +792,6 @@ class SingleTestRunner:
if self.test.protocol is TestProtocol.TAP and stderr is stdout:
stdout = tempfile.TemporaryFile("wb+")
- # Let gdb handle ^C instead of us
- if self.options.gdb:
- previous_sigint_handler = signal.getsignal(signal.SIGINT)
- # Make the meson executable ignore SIGINT while gdb is running.
- signal.signal(signal.SIGINT, signal.SIG_IGN)
-
- def preexec_fn() -> None:
- if self.options.gdb:
- # Restore the SIGINT handler for the child process to
- # ensure it can handle it.
- signal.signal(signal.SIGINT, signal.SIG_DFL)
- else:
- # We don't want setsid() in gdb because gdb needs the
- # terminal in order to handle ^C and not show tcsetpgrp()
- # errors avoid not being able to use the terminal.
- os.setsid()
-
extra_cmd = [] # type: T.List[str]
if self.test.protocol is TestProtocol.GTEST:
gtestname = self.test.name
@@ -702,77 +799,19 @@ class SingleTestRunner:
gtestname = os.path.join(self.test.workdir, self.test.name)
extra_cmd.append('--gtest_output=xml:{}.xml'.format(gtestname))
- p = subprocess.Popen(cmd + extra_cmd,
- stdout=stdout,
- stderr=stderr,
- env=self.env,
- cwd=self.test.workdir,
- preexec_fn=preexec_fn if not is_windows() else None)
- timed_out = False
- kill_test = False
if self.test.timeout is None:
timeout = None
elif self.options.timeout_multiplier is not None:
timeout = self.test.timeout * self.options.timeout_multiplier
else:
timeout = self.test.timeout
- try:
- p.communicate(timeout=timeout)
- except subprocess.TimeoutExpired:
- if self.options.verbose:
- print('{} time out (After {} seconds)'.format(self.test.name, timeout))
- timed_out = True
- except KeyboardInterrupt:
- mlog.warning('CTRL-C detected while running {}'.format(self.test.name))
- kill_test = True
- finally:
- if self.options.gdb:
- # Let us accept ^C again
- signal.signal(signal.SIGINT, previous_sigint_handler)
-
- additional_error = None
-
- if kill_test or timed_out:
- # Python does not provide multiplatform support for
- # killing a process and all its children so we need
- # to roll our own.
- if is_windows():
- subprocess.run(['taskkill', '/F', '/T', '/PID', str(p.pid)])
- else:
- def _send_signal_to_process_group(pgid : int, signum : int) -> None:
- """ sends a signal to a process group """
- try:
- os.killpg(pgid, signum)
- except ProcessLookupError:
- # Sometimes (e.g. with Wine) this happens.
- # There's nothing we can do (maybe the process
- # already died) so carry on.
- pass
-
- # Send a termination signal to the process group that setsid()
- # created - giving it a chance to perform any cleanup.
- _send_signal_to_process_group(p.pid, signal.SIGTERM)
-
- # Make sure the termination signal actually kills the process
- # group, otherwise retry with a SIGKILL.
- try:
- p.communicate(timeout=0.5)
- except subprocess.TimeoutExpired:
- _send_signal_to_process_group(p.pid, signal.SIGKILL)
- try:
- p.communicate(timeout=1)
- except subprocess.TimeoutExpired:
- # An earlier kill attempt has not worked for whatever reason.
- # Try to kill it one last time with a direct call.
- # If the process has spawned children, they will remain around.
- p.kill()
- try:
- p.communicate(timeout=1)
- except subprocess.TimeoutExpired:
- additional_error = 'Test process could not be killed.'
- except ValueError:
- additional_error = 'Could not read output. Maybe the process has redirected its stdout/stderr?'
+ returncode, result, additional_error = await self._run_subprocess(cmd + extra_cmd,
+ timeout=timeout,
+ stdout=stdout,
+ stderr=stderr,
+ env=self.env,
+ cwd=self.test.workdir)
endtime = time.time()
duration = endtime - starttime
if additional_error is None:
@@ -789,17 +828,17 @@ class SingleTestRunner:
else:
stdo = ""
stde = additional_error
- if timed_out:
- return TestRun(self.test, self.test_env, TestResult.TIMEOUT, [], p.returncode, starttime, duration, stdo, stde, cmd)
+ if result:
+ return TestRun(self.test, self.test_env, result, [], returncode, starttime, duration, stdo, stde, cmd)
else:
if self.test.protocol is TestProtocol.EXITCODE:
- return TestRun.make_exitcode(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd)
+ return TestRun.make_exitcode(self.test, self.test_env, returncode, starttime, duration, stdo, stde, cmd)
elif self.test.protocol is TestProtocol.GTEST:
- return TestRun.make_gtest(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd)
+ return TestRun.make_gtest(self.test, self.test_env, returncode, starttime, duration, stdo, stde, cmd)
else:
if self.options.verbose:
print(stdo, end='')
- return TestRun.make_tap(self.test, self.test_env, p.returncode, starttime, duration, stdo, stde, cmd)
+ return TestRun.make_tap(self.test, self.test_env, returncode, starttime, duration, stdo, stde, cmd)
class TestHarness:
@@ -841,7 +880,7 @@ class TestHarness:
def close_logfiles(self) -> None:
for f in ['logfile', 'jsonlogfile']:
- lfile = getattr(self, f)
+ lfile = getattr(self, f)
if lfile:
lfile.close()
setattr(self, f, None)
@@ -892,7 +931,7 @@ class TestHarness:
self.skip_count += 1
elif result.res is TestResult.OK:
self.success_count += 1
- elif result.res is TestResult.FAIL or result.res is TestResult.ERROR:
+ elif result.res in {TestResult.FAIL, TestResult.ERROR, TestResult.INTERRUPT}:
self.fail_count += 1
elif result.res is TestResult.EXPECTEDFAIL:
self.expectedfail_count += 1
@@ -905,7 +944,7 @@ class TestHarness:
tests: T.List[TestSerialisation],
name: str, result: TestRun, i: int) -> None:
ok_statuses = (TestResult.OK, TestResult.EXPECTEDFAIL)
- bad_statuses = (TestResult.FAIL, TestResult.TIMEOUT,
+ bad_statuses = (TestResult.FAIL, TestResult.TIMEOUT, TestResult.INTERRUPT,
TestResult.UNEXPECTEDPASS, TestResult.ERROR)
result_str = '{num:{numlen}}/{testcount} {name:{name_max_len}} {res:{reslen}} {dur:.2f}s'.format(
numlen=len(str(test_count)),
@@ -918,20 +957,15 @@ class TestHarness:
dur=result.duration)
if result.res is TestResult.FAIL:
result_str += ' ' + returncode_to_status(result.returncode)
+ if result.res in bad_statuses:
+ self.collected_failures.append(result_str)
if not self.options.quiet or result.res not in ok_statuses:
- if result.res not in ok_statuses:
- self.collected_failures.append(result_str)
- if mlog.colorize_console():
- if result.res in bad_statuses:
- self.collected_failures.append(result_str)
- decorator = mlog.red
- elif result.res is TestResult.SKIP:
- decorator = mlog.yellow
- else:
- sys.exit('Unreachable code was ... well ... reached.')
- print(decorator(result_str).get_text(True))
- else:
- print(result_str)
+ decorator = mlog.plain
+ if result.res in bad_statuses:
+ decorator = mlog.red
+ elif result.res is TestResult.SKIP:
+ decorator = mlog.yellow
+ print(decorator(result_str).get_text(mlog.colorize_console()))
result_str += "\n\n" + result.get_log()
if result.res in bad_statuses:
if self.options.print_errorlogs:
@@ -956,7 +990,7 @@ class TestHarness:
Skipped: {:<4}
Timeout: {:<4}
''').format(self.success_count, self.expectedfail_count, self.fail_count,
- self.unexpectedpass_count, self.skip_count, self.timeout_count)
+ self.unexpectedpass_count, self.skip_count, self.timeout_count)
print(msg)
if self.logfile:
self.logfile.write(msg)
@@ -1136,8 +1170,14 @@ class TestHarness:
return test.name
def run_tests(self, tests: T.List[TestSerialisation]) -> None:
- executor = None
- futures = [] # type: T.List[T.Tuple[conc.Future[TestRun], int, int, T.List[TestSerialisation], str, int]]
+ # Replace with asyncio.run once we can require Python 3.7
+ loop = asyncio.get_event_loop()
+ loop.run_until_complete(self._run_tests(tests))
+
+ async def _run_tests(self, tests: T.List[TestSerialisation]) -> None:
+ semaphore = asyncio.Semaphore(self.options.num_processes)
+ futures = deque() # type: T.Deque[asyncio.Future]
+ running_tests = dict() # type: T.Dict[asyncio.Future, str]
test_count = len(tests)
name_max_len = max([len(self.get_pretty_suite(test)) for test in tests])
self.open_log_files()
@@ -1145,59 +1185,87 @@ class TestHarness:
if self.options.wd:
os.chdir(self.options.wd)
self.build_data = build.load(os.getcwd())
+ interrupted = False
+ async def run_test(test: SingleTestRunner,
+ name: str, index: int) -> None:
+ async with semaphore:
+ if interrupted or (self.options.repeat > 1 and self.fail_count):
+ return
+ res = await test.run()
+ self.process_test_result(res)
+ self.print_stats(test_count, name_max_len, tests, name, res, index)
+
+ def test_done(f: asyncio.Future) -> None:
+ if not f.cancelled():
+ f.result()
+ futures.remove(f)
+ try:
+ del running_tests[f]
+ except KeyError:
+ pass
+
+ def cancel_one_test(warn: bool) -> None:
+ future = futures.popleft()
+ futures.append(future)
+ if warn:
+ mlog.warning('CTRL-C detected, interrupting {}'.format(running_tests[future]))
+ del running_tests[future]
+ future.cancel()
+
+ def sigterm_handler() -> None:
+ nonlocal interrupted
+ if interrupted:
+ return
+ interrupted = True
+ mlog.warning('Received SIGTERM, exiting')
+ while running_tests:
+ cancel_one_test(False)
+
+ def sigint_handler() -> None:
+ # We always pick the longest-running future that has not been cancelled
+ # If all the tests have been CTRL-C'ed, just stop
+ nonlocal interrupted
+ if interrupted:
+ return
+ if running_tests:
+ cancel_one_test(True)
+ else:
+ mlog.warning('CTRL-C detected, exiting')
+ interrupted = True
+
+ if sys.platform != 'win32':
+ asyncio.get_event_loop().add_signal_handler(signal.SIGINT, sigint_handler)
+ asyncio.get_event_loop().add_signal_handler(signal.SIGTERM, sigterm_handler)
try:
for _ in range(self.options.repeat):
for i, test in enumerate(tests, 1):
visible_name = self.get_pretty_suite(test)
single_test = self.get_test_runner(test)
- if not test.is_parallel or self.options.num_processes == 1 or single_test.options.gdb:
- self.drain_futures(futures)
- futures = []
- res = single_test.run()
- self.process_test_result(res)
- self.print_stats(test_count, name_max_len, tests, visible_name, res, i)
- else:
- if not executor:
- executor = conc.ThreadPoolExecutor(max_workers=self.options.num_processes)
- f = executor.submit(single_test.run)
- futures.append((f, test_count, name_max_len, tests, visible_name, i))
- if self.options.repeat > 1 and self.fail_count:
- break
+ if not test.is_parallel or single_test.options.gdb:
+ await complete_all(futures)
+ future = asyncio.ensure_future(run_test(single_test, visible_name, i))
+ futures.append(future)
+ running_tests[future] = visible_name
+ future.add_done_callback(test_done)
+ if not test.is_parallel or single_test.options.gdb:
+ await complete(future)
if self.options.repeat > 1 and self.fail_count:
break
- self.drain_futures(futures)
+ await complete_all(futures)
self.print_collected_logs()
self.print_summary()
if self.logfilename:
print('Full log written to {}'.format(self.logfilename))
finally:
+ if sys.platform != 'win32':
+ asyncio.get_event_loop().remove_signal_handler(signal.SIGINT)
+ asyncio.get_event_loop().remove_signal_handler(signal.SIGTERM)
os.chdir(startdir)
- def drain_futures(self, futures: T.List[T.Tuple['conc.Future[TestRun]', int, int, T.List[TestSerialisation], str, int]]) -> None:
- for x in futures:
- (result, test_count, name_max_len, tests, name, i) = x
- if self.options.repeat > 1 and self.fail_count:
- result.cancel()
- if self.options.verbose:
- result.result()
- self.process_test_result(result.result())
- self.print_stats(test_count, name_max_len, tests, name, result.result(), i)
-
- def run_special(self) -> int:
- '''Tests run by the user, usually something like "under gdb 1000 times".'''
- if self.is_run:
- raise RuntimeError('Can not use run_special after a full run.')
- tests = self.get_tests()
- if not tests:
- return 0
- self.run_tests(tests)
- return self.total_failure_count()
-
-
def list_tests(th: TestHarness) -> bool:
tests = th.get_tests()
for t in tests:
@@ -1240,6 +1308,10 @@ def run(options: argparse.Namespace) -> int:
if options.wrapper:
check_bin = options.wrapper[0]
+ if sys.platform == 'win32':
+ loop = asyncio.ProactorEventLoop()
+ asyncio.set_event_loop(loop)
+
if check_bin is not None:
exe = ExternalProgram(check_bin, silent=True)
if not exe.found():
@@ -1257,9 +1329,7 @@ def run(options: argparse.Namespace) -> int:
try:
if options.list:
return list_tests(th)
- if not options.args:
- return th.doit()
- return th.run_special()
+ return th.doit()
except TestException as e:
print('Meson test encountered an error:\n')
if os.environ.get('MESON_FORCE_BACKTRACE'):
diff --git a/mesonbuild/scripts/clangformat.py b/mesonbuild/scripts/clangformat.py
index e7a3ff8..062cb43 100644
--- a/mesonbuild/scripts/clangformat.py
+++ b/mesonbuild/scripts/clangformat.py
@@ -25,6 +25,7 @@ def clangformat(exelist: T.List[str], srcdir_name: str, builddir_name: str) -> i
suffixes = set(lang_suffixes['c']).union(set(lang_suffixes['cpp']))
suffixes.add('h')
futures = []
+ returncode = 0
with ThreadPoolExecutor() as e:
for f in (x for suff in suffixes for x in srcdir.glob('**/*.' + suff)):
if f.is_dir():
@@ -32,9 +33,9 @@ def clangformat(exelist: T.List[str], srcdir_name: str, builddir_name: str) -> i
strf = str(f)
if strf.startswith(builddir_name):
continue
- futures.append(e.submit(subprocess.check_call, exelist + ['-style=file', '-i', strf]))
- [x.result() for x in futures]
- return 0
+ futures.append(e.submit(subprocess.run, exelist + ['-style=file', '-i', strf]))
+ returncode = max([x.result().returncode for x in futures])
+ return returncode
def run(args: T.List[str]) -> int:
srcdir_name = args[0]
diff --git a/mesonbuild/scripts/clangtidy.py b/mesonbuild/scripts/clangtidy.py
index dfaf998..8d366c8 100644
--- a/mesonbuild/scripts/clangtidy.py
+++ b/mesonbuild/scripts/clangtidy.py
@@ -22,7 +22,7 @@ import typing as T
from ..compilers import lang_suffixes
-def manual_clangformat(srcdir_name: str, builddir_name: str) -> int:
+def manual_clangtidy(srcdir_name: str, builddir_name: str) -> int:
srcdir = pathlib.Path(srcdir_name)
suffixes = set(lang_suffixes['c']).union(set(lang_suffixes['cpp']))
suffixes.add('h')
@@ -36,10 +36,10 @@ def manual_clangformat(srcdir_name: str, builddir_name: str) -> int:
if strf.startswith(builddir_name):
continue
futures.append(e.submit(subprocess.run, ['clang-tidy', '-p', builddir_name, strf]))
- [max(returncode, x.result().returncode) for x in futures]
+ returncode = max([x.result().returncode for x in futures])
return returncode
-def clangformat(srcdir_name: str, builddir_name: str) -> int:
+def clangtidy(srcdir_name: str, builddir_name: str) -> int:
run_clang_tidy = None
for rct in ('run-clang-tidy', 'run-clang-tidy.py'):
if shutil.which(rct):
@@ -49,10 +49,9 @@ def clangformat(srcdir_name: str, builddir_name: str) -> int:
return subprocess.run([run_clang_tidy, '-p', builddir_name, '^(?!' + re.escape(builddir_name + os.path.sep) +').*$']).returncode
else:
print('Could not find run-clang-tidy, running checks manually.')
- manual_clangformat(srcdir_name, builddir_name)
- return 0
+ return manual_clangtidy(srcdir_name, builddir_name)
def run(args: T.List[str]) -> int:
srcdir_name = args[0]
builddir_name = args[1]
- return clangformat(srcdir_name, builddir_name)
+ return clangtidy(srcdir_name, builddir_name)
diff --git a/run_project_tests.py b/run_project_tests.py
index e4a458e..8bf6437 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -870,6 +870,10 @@ def skippable(suite, test):
if test.endswith('15 llvm'):
return True
+ # This test breaks with gobject-introspection <= 1.58.1
+ if test.endswith('34 gir static lib'):
+ return True
+
# No frameworks test should be skipped on linux CI, as we expect all
# prerequisites to be installed
if mesonlib.is_linux():
diff --git a/run_unittests.py b/run_unittests.py
index f0c2f65..9815058 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from mesonbuild.compilers.objc import AppleClangObjCCompiler
import time
import stat
import subprocess
@@ -885,11 +886,11 @@ class InternalTests(unittest.TestCase):
def fake_call_pkgbin(self, args, env=None):
if '--libs' not in args:
return 0, '', ''
- if args[0] == 'foo':
+ if args[-1] == 'foo':
return 0, '-L{} -lfoo -L{} -lbar'.format(p2.as_posix(), p1.as_posix()), ''
- if args[0] == 'bar':
+ if args[-1] == 'bar':
return 0, '-L{} -lbar'.format(p2.as_posix()), ''
- if args[0] == 'internal':
+ if args[-1] == 'internal':
return 0, '-L{} -lpthread -lm -lc -lrt -ldl'.format(p1.as_posix()), ''
old_call = PkgConfigDependency._call_pkgbin
@@ -1186,7 +1187,7 @@ class InternalTests(unittest.TestCase):
]:
d = mesonbuild.depfile.DepFile(f)
deps = d.get_all_dependencies(target)
- self.assertEqual(deps, expdeps)
+ self.assertEqual(sorted(deps), sorted(expdeps))
def test_log_once(self):
f = io.StringIO()
@@ -2942,20 +2943,22 @@ class AllPlatformTests(BasePlatformTests):
# the source tree leads to all kinds of trouble.
with tempfile.TemporaryDirectory() as project_dir:
with open(os.path.join(project_dir, 'meson.build'), 'w') as ofile:
- ofile.write('''project('disttest', 'c', version : '1.4.3')
-e = executable('distexe', 'distexe.c')
-test('dist test', e)
-subproject('vcssub', required : false)
-subproject('tarballsub', required : false)
-''')
+ ofile.write(textwrap.dedent('''\
+ project('disttest', 'c', version : '1.4.3')
+ e = executable('distexe', 'distexe.c')
+ test('dist test', e)
+ subproject('vcssub', required : false)
+ subproject('tarballsub', required : false)
+ '''))
with open(os.path.join(project_dir, 'distexe.c'), 'w') as ofile:
- ofile.write('''#include<stdio.h>
+ ofile.write(textwrap.dedent('''\
+ #include<stdio.h>
-int main(int argc, char **argv) {
- printf("I am a distribution test.\\n");
- return 0;
-}
-''')
+ int main(int argc, char **argv) {
+ printf("I am a distribution test.\\n");
+ return 0;
+ }
+ '''))
xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz')
xz_checksumfile = xz_distfile + '.sha256sum'
zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip')
@@ -3614,8 +3617,8 @@ int main(int argc, char **argv) {
"""
tdir = os.path.join(self.unit_test_dir, '30 shared_mod linking')
out = self.init(tdir)
- msg = ('''WARNING: target links against shared modules. This is not
-recommended as it is not supported on some platforms''')
+ msg = ('WARNING: target links against shared modules. This is not '
+ 'recommended as it is not supported on some platforms')
self.assertIn(msg, out)
def test_ndebug_if_release_disabled(self):
@@ -7264,16 +7267,18 @@ class LinuxlikeTests(BasePlatformTests):
testdir = os.path.join(self.unit_test_dir, '61 identity cross')
nativefile = tempfile.NamedTemporaryFile(mode='w')
- nativefile.write('''[binaries]
-c = ['{0}']
-'''.format(os.path.join(testdir, 'build_wrapper.py')))
+ nativefile.write(textwrap.dedent('''\
+ [binaries]
+ c = ['{0}']
+ '''.format(os.path.join(testdir, 'build_wrapper.py'))))
nativefile.flush()
self.meson_native_file = nativefile.name
crossfile = tempfile.NamedTemporaryFile(mode='w')
- crossfile.write('''[binaries]
-c = ['{0}']
-'''.format(os.path.join(testdir, 'host_wrapper.py')))
+ crossfile.write(textwrap.dedent('''\
+ [binaries]
+ c = ['{0}']
+ '''.format(os.path.join(testdir, 'host_wrapper.py'))))
crossfile.flush()
self.meson_cross_file = crossfile.name
@@ -7286,9 +7291,10 @@ c = ['{0}']
'CC_FOR_BUILD': '"' + os.path.join(testdir, 'build_wrapper.py') + '"',
}
crossfile = tempfile.NamedTemporaryFile(mode='w')
- crossfile.write('''[binaries]
-c = ['{0}']
-'''.format(os.path.join(testdir, 'host_wrapper.py')))
+ crossfile.write(textwrap.dedent('''\
+ [binaries]
+ c = ['{0}']
+ '''.format(os.path.join(testdir, 'host_wrapper.py'))))
crossfile.flush()
self.meson_cross_file = crossfile.name
# TODO should someday be explicit about build platform only here
@@ -7334,6 +7340,11 @@ c = ['{0}']
with mock.patch.dict(os.environ, {envvar: name}):
env = get_fake_env()
comp = getattr(env, 'detect_{}_compiler'.format(lang))(MachineChoice.HOST)
+ if isinstance(comp, (mesonbuild.compilers.AppleClangCCompiler,
+ mesonbuild.compilers.AppleClangCPPCompiler,
+ mesonbuild.compilers.AppleClangObjCCompiler,
+ mesonbuild.compilers.AppleClangObjCPPCompiler)):
+ raise unittest.SkipTest('AppleClang is currently only supported with ld64')
if lang != 'rust' and comp.use_linker_args('bfd') == []:
raise unittest.SkipTest(
'Compiler {} does not support using alternative linkers'.format(comp.id))
@@ -7349,8 +7360,9 @@ c = ['{0}']
self._check_ld('ld.lld', 'lld', 'c', 'ld.lld')
@skip_if_not_language('rust')
+ @skipIfNoExecutable('ld.gold') # need an additional check here because _check_ld checks for gcc
def test_ld_environment_variable_rust(self):
- self._check_ld('ld.gold', 'gold', 'rust', 'ld.gold')
+ self._check_ld('gcc', 'gcc -fuse-ld=gold', 'rust', 'ld.gold')
def test_ld_environment_variable_cpp(self):
self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold')
diff --git a/test cases/common/14 configure file/meson.build b/test cases/common/14 configure file/meson.build
index f40dc52..f7e0eeb 100644
--- a/test cases/common/14 configure file/meson.build
+++ b/test cases/common/14 configure file/meson.build
@@ -10,6 +10,7 @@ conf.set('BE_TRUE', true)
assert(conf.get('var') == 'mystring', 'Get function is not working.')
assert(conf.get('var', 'default') == 'mystring', 'Get function is not working.')
assert(conf.get('notthere', 'default') == 'default', 'Default value getting is not working.')
+assert(conf.keys() == ['BE_TRUE', 'other', 'second', 'var'], 'Keys function is not working')
cfile = configure_file(input : 'config.h.in',
output : 'config.h',
diff --git a/test cases/common/231 external project/libfoo/configure b/test cases/common/231 external project/libfoo/configure
index a867b48..0e4aa72 100755
--- a/test cases/common/231 external project/libfoo/configure
+++ b/test cases/common/231 external project/libfoo/configure
@@ -27,7 +27,7 @@ case $i in
esac
done
-DEP_ARGS=$(pkg-config somelib --cflags --libs)
+DEP_ARGS=$(pkg-config --cflags --libs somelib)
cat > Makefile << EOL
all: libfoo.$LIBEXT
diff --git a/test cases/common/28 multiline string/meson.build b/test cases/common/28 multiline string/meson.build
index 9cec114..a87d29a 100644
--- a/test cases/common/28 multiline string/meson.build
+++ b/test cases/common/28 multiline string/meson.build
@@ -26,6 +26,8 @@ endif
cc = meson.get_compiler('c')
prog = '''
+#include <stdio.h>
+
int main(void) {
int num = 1;
printf("%d\n", num);
diff --git a/test cases/failing/76 link with shared module on osx/test.json b/test cases/failing/76 link with shared module on osx/test.json
index 4e2856f..0a32674 100644
--- a/test cases/failing/76 link with shared module on osx/test.json
+++ b/test cases/failing/76 link with shared module on osx/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/76 link with shared module on osx/meson.build:8:0: ERROR: target links against shared modules."
+ "line": "test cases/failing/76 link with shared module on osx/meson.build:8:0: ERROR: target links against shared modules. This is not permitted on OSX"
}
]
}
diff --git a/test cases/frameworks/34 gir static lib/meson.build b/test cases/frameworks/34 gir static lib/meson.build
new file mode 100644
index 0000000..d7ab9bf
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/meson.build
@@ -0,0 +1,18 @@
+project('gobject-introspection-static-helper', 'c')
+
+gir = find_program('g-ir-scanner', required: false)
+if not gir.found()
+ error('MESON_SKIP_TEST g-ir-scanner not found.')
+endif
+
+gobject_introspection = dependency('gobject-introspection-1.0')
+# This won't work without https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/72
+if gobject_introspection.version().version_compare('< 1.58.1')
+ error('MESON_SKIP_TEST gobject-introspection is too old to support static libraries')
+endif
+
+gnome = import('gnome')
+gobj = dependency('gobject-2.0')
+
+subdir('statichelper')
+subdir('subdir/gir')
diff --git a/test cases/frameworks/34 gir static lib/statichelper/meson-sample.c b/test cases/frameworks/34 gir static lib/statichelper/meson-sample.c
new file mode 100644
index 0000000..2ed9cdf
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/statichelper/meson-sample.c
@@ -0,0 +1,126 @@
+#include "meson-sample.h"
+
+typedef struct _MesonSamplePrivate
+{
+ gchar *msg;
+} MesonSamplePrivate;
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (MesonSample, meson_sample, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_MSG,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+/**
+ * meson_sample_new:
+ * @msg: The message to set.
+ *
+ * Allocates a new #MesonSample.
+ *
+ * Returns: (transfer full): a #MesonSample.
+ */
+MesonSample *
+meson_sample_new (const gchar *msg)
+{
+ g_return_val_if_fail (msg != NULL, NULL);
+
+ return g_object_new (MESON_TYPE_SAMPLE,
+ "message", msg,
+ NULL);
+}
+
+static void
+meson_sample_finalize (GObject *object)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ g_clear_pointer (&priv->msg, g_free);
+
+ G_OBJECT_CLASS (meson_sample_parent_class)->finalize (object);
+}
+
+static void
+meson_sample_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ g_value_set_string (value, priv->msg);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sample_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ priv->msg = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sample_class_init (MesonSampleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meson_sample_finalize;
+ object_class->get_property = meson_sample_get_property;
+ object_class->set_property = meson_sample_set_property;
+
+ gParamSpecs [PROP_MSG] =
+ g_param_spec_string ("message",
+ "Message",
+ "The message to print.",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+meson_sample_init (MesonSample *self)
+{
+}
+
+/**
+ * meson_sample_print_message:
+ * @self: a #MesonSample.
+ *
+ * Prints the message.
+ *
+ */
+void
+meson_sample_print_message (MesonSample *self)
+{
+ MesonSamplePrivate *priv;
+
+ g_return_if_fail (MESON_IS_SAMPLE (self));
+
+ priv = meson_sample_get_instance_private (self);
+
+ g_print ("Message: %s\n", priv->msg);
+}
diff --git a/test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in b/test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in
new file mode 100644
index 0000000..d0ab29e
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/statichelper/meson-sample.h.in
@@ -0,0 +1,22 @@
+#ifndef MESON_SAMPLE_H
+#define MESON_SAMPLE_H
+
+#include <@HEADER@>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_SAMPLE (meson_sample_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (MesonSample, meson_sample, MESON, SAMPLE, GObject)
+
+struct _MesonSampleClass {
+ GObjectClass parent_class;
+};
+
+
+MesonSample *meson_sample_new (const gchar *msg);
+void meson_sample_print_message (MesonSample *self);
+
+G_END_DECLS
+
+#endif /* MESON_SAMPLE_H */
diff --git a/test cases/frameworks/34 gir static lib/statichelper/meson.build b/test cases/frameworks/34 gir static lib/statichelper/meson.build
new file mode 100644
index 0000000..a815372
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/statichelper/meson.build
@@ -0,0 +1,22 @@
+conf = configuration_data()
+conf.set('HEADER', 'glib-object.h')
+
+meson_sample_header = configure_file(
+ input : 'meson-sample.h.in',
+ output : 'meson-sample.h',
+ configuration : conf)
+
+statichelper_sources = files('meson-sample.c') + [meson_sample_header]
+
+statichelper_lib = static_library(
+ 'statichelper',
+ sources : statichelper_sources,
+ dependencies : gobj,
+)
+
+statichelper_inc = include_directories('.')
+statichelper_dep = declare_dependency(
+ link_with: statichelper_lib,
+ dependencies : gobj,
+ include_directories : [statichelper_inc],
+)
diff --git a/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c b/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c
new file mode 100644
index 0000000..2d58a10
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.c
@@ -0,0 +1,124 @@
+#include "meson-subsample.h"
+
+struct _MesonSubSample
+{
+ MesonSample parent_instance;
+
+ gchar *msg;
+};
+
+G_DEFINE_TYPE (MesonSubSample, meson_sub_sample, MESON_TYPE_SAMPLE)
+
+enum {
+ PROP_0,
+ PROP_MSG,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+/**
+ * meson_sub_sample_new:
+ * @msg: The message to set.
+ *
+ * Allocates a new #MesonSubSample.
+ *
+ * Returns: (transfer full): a #MesonSubSample.
+ */
+MesonSubSample *
+meson_sub_sample_new (const gchar *msg)
+{
+ g_return_val_if_fail (msg != NULL, NULL);
+
+ return g_object_new (MESON_TYPE_SUB_SAMPLE,
+ "message", msg,
+ NULL);
+}
+
+static void
+meson_sub_sample_finalize (GObject *object)
+{
+ MesonSubSample *self = (MesonSubSample *)object;
+
+ g_clear_pointer (&self->msg, g_free);
+
+ G_OBJECT_CLASS (meson_sub_sample_parent_class)->finalize (object);
+}
+
+static void
+meson_sub_sample_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSubSample *self = MESON_SUB_SAMPLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ g_value_set_string (value, self->msg);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sub_sample_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSubSample *self = MESON_SUB_SAMPLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ self->msg = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sub_sample_class_init (MesonSubSampleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meson_sub_sample_finalize;
+ object_class->get_property = meson_sub_sample_get_property;
+ object_class->set_property = meson_sub_sample_set_property;
+
+ gParamSpecs [PROP_MSG] =
+ g_param_spec_string ("message",
+ "Message",
+ "The message to print.",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+meson_sub_sample_init (MesonSubSample *self)
+{
+}
+
+/**
+ * meson_sub_sample_print_message:
+ * @self: a #MesonSubSample.
+ *
+ * Prints the message.
+ *
+ * Returns: Nothing.
+ */
+void
+meson_sub_sample_print_message (MesonSubSample *self)
+{
+ g_return_if_fail (MESON_IS_SUB_SAMPLE (self));
+
+ g_print ("Message: %s\n", self->msg);
+}
diff --git a/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h b/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h
new file mode 100644
index 0000000..9d34a08
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/subdir/gir/meson-subsample.h
@@ -0,0 +1,17 @@
+#ifndef MESON_SUB_SAMPLE_H
+#define MESON_SUB_SAMPLE_H
+
+#include <glib-object.h>
+#include <meson-sample.h>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_SUB_SAMPLE (meson_sub_sample_get_type())
+
+G_DECLARE_FINAL_TYPE (MesonSubSample, meson_sub_sample, MESON, SUB_SAMPLE, MesonSample)
+
+MesonSubSample *meson_sub_sample_new (const gchar *msg);
+
+G_END_DECLS
+
+#endif /* MESON_SUB_SAMPLE_H */
diff --git a/test cases/frameworks/34 gir static lib/subdir/gir/meson.build b/test cases/frameworks/34 gir static lib/subdir/gir/meson.build
new file mode 100644
index 0000000..b26f04e
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/subdir/gir/meson.build
@@ -0,0 +1,28 @@
+libsources = ['meson-subsample.c', 'meson-subsample.h']
+
+girlib = shared_library(
+ 'girlib',
+ sources : libsources,
+ dependencies : [gobj, statichelper_dep],
+ install : true
+)
+
+girexe = executable(
+ 'girprog',
+ sources : 'prog.c',
+ dependencies : [gobj, statichelper_dep],
+ link_with : girlib
+)
+
+gnome.generate_gir(
+ girlib, statichelper_lib,
+ sources : [ libsources, statichelper_sources ],
+ nsversion : '1.0',
+ namespace : 'Meson',
+ symbol_prefix : 'meson_',
+ identifier_prefix : 'Meson',
+ includes : ['GObject-2.0'],
+ install : true
+)
+
+test('gobject introspection/subproject/c', girexe)
diff --git a/test cases/frameworks/34 gir static lib/subdir/gir/prog.c b/test cases/frameworks/34 gir static lib/subdir/gir/prog.c
new file mode 100644
index 0000000..f25c9d8
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/subdir/gir/prog.c
@@ -0,0 +1,12 @@
+#include "meson-subsample.h"
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ MesonSample * i = (MesonSample*) meson_sub_sample_new ("Hello, sub/meson/c!");
+ meson_sample_print_message (i);
+ g_object_unref (i);
+
+ return 0;
+}
diff --git a/test cases/frameworks/34 gir static lib/test.json b/test cases/frameworks/34 gir static lib/test.json
new file mode 100644
index 0000000..a99e5a7
--- /dev/null
+++ b/test cases/frameworks/34 gir static lib/test.json
@@ -0,0 +1,8 @@
+{
+ "installed": [
+ {"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"},
+ {"type": "expr", "file": "usr/lib/?libgirlib.so"},
+ {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirlib.dll.a"},
+ {"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"}
+ ]
+}
diff --git a/test cases/frameworks/7 gnome/mkenums/enums.c.in b/test cases/frameworks/7 gnome/mkenums/enums.c.in
index 62e1adc..1c19d8f 100644
--- a/test cases/frameworks/7 gnome/mkenums/enums.c.in
+++ b/test cases/frameworks/7 gnome/mkenums/enums.c.in
@@ -13,9 +13,9 @@
/*** BEGIN value-header ***/
GType
@enum_name@_get_type(void) {
- static volatile gsize g_define_type_id__volatile = 0;
+ static gsize static_g_define_type_id = 0;
- if(g_once_init_enter(&g_define_type_id__volatile)) {
+ if(g_once_init_enter(&static_g_define_type_id)) {
static const G@Type@Value values [] = {
/*** END value-header ***/
@@ -29,10 +29,10 @@ GType
GType g_define_type_id =
g_@type@_register_static(g_intern_static_string("@EnumName@"), values);
- g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
+ g_once_init_leave(&static_g_define_type_id, g_define_type_id);
}
- return g_define_type_id__volatile;
+ return static_g_define_type_id;
}
/*** END value-tail ***/
diff --git a/test cases/frameworks/7 gnome/mkenums/enums2.c.in b/test cases/frameworks/7 gnome/mkenums/enums2.c.in
index 62e1adc..1c19d8f 100644
--- a/test cases/frameworks/7 gnome/mkenums/enums2.c.in
+++ b/test cases/frameworks/7 gnome/mkenums/enums2.c.in
@@ -13,9 +13,9 @@
/*** BEGIN value-header ***/
GType
@enum_name@_get_type(void) {
- static volatile gsize g_define_type_id__volatile = 0;
+ static gsize static_g_define_type_id = 0;
- if(g_once_init_enter(&g_define_type_id__volatile)) {
+ if(g_once_init_enter(&static_g_define_type_id)) {
static const G@Type@Value values [] = {
/*** END value-header ***/
@@ -29,10 +29,10 @@ GType
GType g_define_type_id =
g_@type@_register_static(g_intern_static_string("@EnumName@"), values);
- g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
+ g_once_init_leave(&static_g_define_type_id, g_define_type_id);
}
- return g_define_type_id__volatile;
+ return static_g_define_type_id;
}
/*** END value-tail ***/
diff --git a/test cases/frameworks/7 gnome/mkenums/meson.build b/test cases/frameworks/7 gnome/mkenums/meson.build
index 3d7adf0..8ff05ba 100644
--- a/test cases/frameworks/7 gnome/mkenums/meson.build
+++ b/test cases/frameworks/7 gnome/mkenums/meson.build
@@ -89,9 +89,9 @@ enums_c3 = gnome.mkenums('enums3.c',
vhead : '''
GType
@enum_name@_get_type(void) {
- static volatile gsize g_define_type_id__volatile = 0;
+ static gsize static_g_define_type_id = 0;
- if(g_once_init_enter(&g_define_type_id__volatile)) {
+ if(g_once_init_enter(&static_g_define_type_id)) {
static const G@Type@Value values [] = {
''',
vprod : ''' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },''',
@@ -100,10 +100,10 @@ GType
GType g_define_type_id =
g_@type@_register_static(g_intern_static_string("@EnumName@"), values);
- g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
+ g_once_init_leave(&static_g_define_type_id, g_define_type_id);
}
- return g_define_type_id__volatile;
+ return static_g_define_type_id;
}
''')
diff --git a/test cases/frameworks/8 flex/lexer.l b/test cases/frameworks/8 flex/lexer.l
index 85293b2..952eeea 100644
--- a/test cases/frameworks/8 flex/lexer.l
+++ b/test cases/frameworks/8 flex/lexer.l
@@ -1,6 +1,9 @@
%{
#include <stdlib.h>
#include "parser.tab.h"
+
+extern int yylex(void);
+extern int yyerror();
%}
%%
diff --git a/test cases/frameworks/8 flex/parser.y b/test cases/frameworks/8 flex/parser.y
index ff8754f..663f2f3 100644
--- a/test cases/frameworks/8 flex/parser.y
+++ b/test cases/frameworks/8 flex/parser.y
@@ -1,3 +1,8 @@
+%{
+extern int yylex(void);
+extern int yyerror();
+%}
+
%token BOOLEAN
%%
diff --git a/test cases/rust/2 sharedlib/meson.build b/test cases/rust/2 sharedlib/meson.build
index 42f6e23..aac2968 100644
--- a/test cases/rust/2 sharedlib/meson.build
+++ b/test cases/rust/2 sharedlib/meson.build
@@ -1,5 +1,9 @@
project('rust shared library', 'rust')
+if host_machine.system() == 'darwin'
+ error('MESON_SKIP_TEST: doesnt work right on macos, please fix!')
+endif
+
l = shared_library('stuff', 'stuff.rs', install : true)
e = executable('prog', 'prog.rs', link_with : l, install : true)
diff --git a/test cases/rust/4 polyglot/meson.build b/test cases/rust/4 polyglot/meson.build
index b7eef57..4955516 100644
--- a/test cases/rust/4 polyglot/meson.build
+++ b/test cases/rust/4 polyglot/meson.build
@@ -1,5 +1,9 @@
project('rust and c polyglot executable', 'c', 'rust')
+if host_machine.system() == 'darwin'
+ error('MESON_SKIP_TEST: doesnt work right on macos, please fix!')
+endif
+
l = library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true)
e = executable('prog', 'prog.c', link_with : l, install : true)
test('polyglottest', e)
diff --git a/test cases/unit/59 introspect buildoptions/meson.build b/test cases/unit/59 introspect buildoptions/meson.build
index 16df028..9cfdc2c 100644
--- a/test cases/unit/59 introspect buildoptions/meson.build
+++ b/test cases/unit/59 introspect buildoptions/meson.build
@@ -1,4 +1,4 @@
-project('introspect buildargs', ['c'], default_options: ['c_std=c11', 'cpp_std=c++14', 'buildtype=release'])
+project('introspect buildargs', ['c'], default_options: ['c_std=c99', 'cpp_std=c++14', 'buildtype=release'])
subA = subproject('projectA')
diff --git a/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template b/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template
index 5ecdd2d..85d74d1 100644
--- a/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template
+++ b/test cases/vala/8 generated sources/dependency-generated/enum-types.c.template
@@ -14,9 +14,9 @@
GType
@enum_name@_get_type (void)
{
- static volatile gsize g_define_type_id__volatile = 0;
+ static gsize static_g_define_type_id = 0;
- if (g_once_init_enter (&g_define_type_id__volatile)) {
+ if (g_once_init_enter (&static_g_define_type_id)) {
static const G@Type@Value values[] = {
/*** END value-header ***/
@@ -30,10 +30,10 @@ GType
GType g_define_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
- g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ g_once_init_leave (&static_g_define_type_id, g_define_type_id);
}
- return g_define_type_id__volatile;
+ return static_g_define_type_id;
}
/*** END value-tail ***/