aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/cygwin.yml7
-rw-r--r--.github/workflows/lint.yml (renamed from .github/workflows/lint_mypy.yml)13
-rw-r--r--.github/workflows/website.yml7
-rw-r--r--README.md2
-rw-r--r--azure-pipelines.yml2
-rwxr-xr-xci/ciimage/bionic/install.sh9
-rw-r--r--ci/run.ps12
-rw-r--r--docs/markdown/Continuous-Integration.md2
-rw-r--r--docs/markdown/Getting-meson.md4
-rw-r--r--docs/markdown/Getting-meson_ptbr.md4
-rw-r--r--docs/markdown/Gnome-module.md7
-rw-r--r--docs/markdown/RPM-module.md16
-rw-r--r--docs/markdown/Release-notes-for-0.61.0.md138
-rw-r--r--docs/markdown/Running-Meson.md2
-rw-r--r--docs/markdown/Rust-module.md10
-rw-r--r--docs/markdown/Subprojects.md2
-rw-r--r--docs/markdown/Users.md2
-rw-r--r--docs/markdown/fallback-wraptool.md43
-rw-r--r--docs/markdown/index.md12
-rw-r--r--docs/markdown/snippets/about_minimum_python_version.md7
-rw-r--r--docs/markdown/snippets/armclang-support.md6
-rw-r--r--docs/markdown/snippets/check_false_warning.md14
-rw-r--r--docs/markdown/snippets/cmake_deprecated.md7
-rw-r--r--docs/markdown/snippets/extract-more-objects.md4
-rw-r--r--docs/markdown/snippets/fix_backend_startup_project.md4
-rw-r--r--docs/markdown/snippets/install_symlink.md11
-rw-r--r--docs/markdown/snippets/removing_rpm_module.md10
-rw-r--r--docs/markdown/snippets/rewriter_extra_files.md26
-rw-r--r--docs/markdown/snippets/sccache.md5
-rw-r--r--docs/markdown/snippets/vs_2022.md10
-rw-r--r--docs/markdown/snippets/windows_custom_targets.md22
-rw-r--r--docs/meson.build16
-rw-r--r--docs/refman/generatorbase.py5
-rw-r--r--docs/refman/generatorjson.py7
-rw-r--r--docs/refman/generatorman.py382
-rw-r--r--docs/refman/main.py4
-rw-r--r--docs/sitemap.txt3
-rw-r--r--docs/theme/extra/templates/navbar_links.html1
-rw-r--r--docs/yaml/builtins/meson.yaml31
-rw-r--r--docs/yaml/objects/cfg_data.yaml13
-rw-r--r--docs/yaml/objects/dep.yaml2
-rw-r--r--docs/yaml/objects/feature.yaml2
-rw-r--r--man/meson.12
-rw-r--r--mesonbuild/backend/backends.py272
-rw-r--r--mesonbuild/backend/ninjabackend.py3
-rw-r--r--mesonbuild/build.py277
-rw-r--r--mesonbuild/cmake/data/__init__.py (renamed from test cases/unit/98 install all targets/bar-custom.txt)0
-rw-r--r--mesonbuild/cmake/interpreter.py4
-rw-r--r--mesonbuild/compilers/c.py17
-rw-r--r--mesonbuild/compilers/compilers.py2
-rw-r--r--mesonbuild/compilers/cpp.py28
-rw-r--r--mesonbuild/compilers/cs.py14
-rw-r--r--mesonbuild/compilers/cuda.py5
-rw-r--r--mesonbuild/compilers/d.py10
-rw-r--r--mesonbuild/compilers/detect.py28
-rw-r--r--mesonbuild/compilers/fortran.py33
-rw-r--r--mesonbuild/compilers/java.py2
-rw-r--r--mesonbuild/compilers/mixins/arm.py9
-rw-r--r--mesonbuild/compilers/mixins/c2000.py3
-rw-r--r--mesonbuild/compilers/mixins/ccrx.py3
-rw-r--r--mesonbuild/compilers/mixins/clang.py3
-rw-r--r--mesonbuild/compilers/mixins/clike.py2
-rw-r--r--mesonbuild/compilers/mixins/compcert.py3
-rw-r--r--mesonbuild/compilers/mixins/elbrus.py3
-rw-r--r--mesonbuild/compilers/mixins/gnu.py2
-rw-r--r--mesonbuild/compilers/mixins/intel.py6
-rw-r--r--mesonbuild/compilers/mixins/islinker.py2
-rw-r--r--mesonbuild/compilers/mixins/pgi.py3
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py13
-rw-r--r--mesonbuild/compilers/mixins/xc16.py3
-rw-r--r--mesonbuild/compilers/rust.py11
-rw-r--r--mesonbuild/compilers/swift.py2
-rw-r--r--mesonbuild/compilers/vala.py2
-rw-r--r--mesonbuild/coredata.py7
-rw-r--r--mesonbuild/dependencies/base.py18
-rw-r--r--mesonbuild/dependencies/boost.py2
-rw-r--r--mesonbuild/dependencies/cmake.py4
-rw-r--r--mesonbuild/dependencies/data/__init__.py (renamed from test cases/unit/98 install all targets/bar-devel.h)0
-rw-r--r--mesonbuild/dependencies/hdf5.py2
-rw-r--r--mesonbuild/dependencies/pkgconfig.py28
-rw-r--r--mesonbuild/dependencies/qt.py12
-rw-r--r--mesonbuild/depfile.py35
-rw-r--r--mesonbuild/envconfig.py27
-rw-r--r--mesonbuild/interpreter/__init__.py4
-rw-r--r--mesonbuild/interpreter/interpreter.py42
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py303
-rw-r--r--mesonbuild/interpreter/kwargs.py27
-rw-r--r--mesonbuild/interpreter/mesonmain.py46
-rw-r--r--mesonbuild/interpreterbase/decorators.py8
-rw-r--r--mesonbuild/linkers/linkers.py24
-rw-r--r--mesonbuild/mesondata.py381
-rw-r--r--mesonbuild/mesonlib/universal.py20
-rw-r--r--mesonbuild/mesonlib/vsenv.py23
-rw-r--r--mesonbuild/mesonmain.py18
-rw-r--r--mesonbuild/minstall.py5
-rw-r--r--mesonbuild/mlog.py2
-rw-r--r--mesonbuild/modules/__init__.py9
-rw-r--r--mesonbuild/modules/cmake.py16
-rw-r--r--mesonbuild/modules/dlang.py13
-rw-r--r--mesonbuild/modules/fs.py1
-rw-r--r--mesonbuild/modules/gnome.py637
-rw-r--r--mesonbuild/modules/pkgconfig.py3
-rw-r--r--mesonbuild/modules/python.py29
-rw-r--r--mesonbuild/modules/python3.py3
-rw-r--r--mesonbuild/modules/qt6.py2
-rw-r--r--mesonbuild/modules/rpm.py186
-rw-r--r--mesonbuild/modules/sourceset.py8
-rw-r--r--mesonbuild/modules/unstable_simd.py6
-rw-r--r--mesonbuild/mparser.py35
-rwxr-xr-xmesonbuild/msubprojects.py19
-rw-r--r--mesonbuild/scripts/yelphelper.py133
-rw-r--r--mesonbuild/wrap/wrap.py36
-rwxr-xr-xpackaging/createmsi.py2
-rwxr-xr-xrun_meson_command_tests.py2
-rwxr-xr-xrun_mypy.py2
-rwxr-xr-xrun_project_tests.py3
-rwxr-xr-xrun_tests.py7
-rw-r--r--setup.cfg6
-rw-r--r--setup.py4
-rw-r--r--test cases/common/126 generated llvm ir/meson.build2
-rw-r--r--test cases/common/14 configure file/meson.build3
-rw-r--r--test cases/common/187 args flattening/meson.build8
-rw-r--r--test cases/common/246 dependency fallbacks/meson.build (renamed from test cases/common/245 dependency fallbacks/meson.build)0
-rw-r--r--test cases/common/246 dependency fallbacks/subprojects/png/meson.build (renamed from test cases/common/245 dependency fallbacks/subprojects/png/meson.build)0
-rw-r--r--test cases/common/247 deprecated option/meson.build (renamed from test cases/common/245 deprecated option/meson.build)0
-rw-r--r--test cases/common/247 deprecated option/meson_options.txt (renamed from test cases/common/245 deprecated option/meson_options.txt)0
-rw-r--r--test cases/common/247 deprecated option/test.json (renamed from test cases/common/245 deprecated option/test.json)0
-rw-r--r--test cases/common/248 install_emptydir/meson.build (renamed from test cases/common/246 install_emptydir/meson.build)0
-rw-r--r--test cases/common/248 install_emptydir/test.json (renamed from test cases/common/246 install_emptydir/test.json)0
-rw-r--r--test cases/common/249 install_symlink/datafile.dat (renamed from test cases/common/247 install_symlink/datafile.dat)0
-rw-r--r--test cases/common/249 install_symlink/meson.build (renamed from test cases/common/247 install_symlink/meson.build)0
-rw-r--r--test cases/common/249 install_symlink/test.json (renamed from test cases/common/247 install_symlink/test.json)0
-rw-r--r--test cases/common/250 system include dir/lib/lib.hpp4
-rw-r--r--test cases/common/250 system include dir/main.cpp3
-rw-r--r--test cases/common/250 system include dir/meson.build13
-rw-r--r--test cases/common/44 pkgconfig-gen/answer.c3
-rw-r--r--test cases/common/44 pkgconfig-gen/foo.c7
-rw-r--r--test cases/common/44 pkgconfig-gen/meson.build31
-rw-r--r--test cases/common/44 pkgconfig-gen/test.json2
-rw-r--r--test cases/failing/101 no glib-compile-resources/test.json2
-rw-r--r--test cases/failing/107 feature require.bis/meson.build (renamed from test cases/failing/106 feature require.bis/meson.build)0
-rw-r--r--test cases/failing/107 feature require.bis/meson_options.txt (renamed from test cases/failing/106 feature require.bis/meson_options.txt)0
-rw-r--r--test cases/failing/107 feature require.bis/test.json (renamed from test cases/failing/106 feature require.bis/test.json)0
-rw-r--r--test cases/failing/108 no build get_external_property/meson.build (renamed from test cases/failing/107 no build get_external_property/meson.build)0
-rw-r--r--test cases/failing/108 no build get_external_property/test.json (renamed from test cases/failing/107 no build get_external_property/test.json)2
-rw-r--r--test cases/failing/109 enter subdir twice/meson.build (renamed from test cases/failing/108 enter subdir twice/meson.build)0
-rw-r--r--test cases/failing/109 enter subdir twice/sub/meson.build (renamed from test cases/failing/108 enter subdir twice/sub/meson.build)0
-rw-r--r--test cases/failing/109 enter subdir twice/test.json (renamed from test cases/failing/108 enter subdir twice/test.json)2
-rw-r--r--test cases/failing/111 invalid fstring/109 invalid fstring/meson.build (renamed from test cases/failing/109 invalid fstring/meson.build)0
-rw-r--r--test cases/failing/111 invalid fstring/109 invalid fstring/test.json (renamed from test cases/failing/109 invalid fstring/test.json)0
-rw-r--r--test cases/failing/111 invalid fstring/meson.build (renamed from test cases/failing/110 invalid fstring/meson.build)0
-rw-r--r--test cases/failing/111 invalid fstring/test.json (renamed from test cases/failing/110 invalid fstring/test.json)2
-rw-r--r--test cases/failing/112 compiler argument checking/meson.build (renamed from test cases/failing/111 compiler argument checking/meson.build)0
-rw-r--r--test cases/failing/112 compiler argument checking/test.json (renamed from test cases/failing/111 compiler argument checking/test.json)2
-rw-r--r--test cases/failing/113 empty fallback/meson.build (renamed from test cases/failing/112 empty fallback/meson.build)0
-rw-r--r--test cases/failing/113 empty fallback/subprojects/foo/meson.build (renamed from test cases/failing/112 empty fallback/subprojects/foo/meson.build)0
-rw-r--r--test cases/failing/113 empty fallback/test.json (renamed from test cases/failing/112 empty fallback/test.json)2
-rw-r--r--test cases/failing/114 cmake executable dependency/meson.build (renamed from test cases/failing/113 cmake executable dependency/meson.build)0
-rw-r--r--test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt (renamed from test cases/failing/113 cmake executable dependency/subprojects/cmlib/CMakeLists.txt)0
-rw-r--r--test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c (renamed from test cases/failing/113 cmake executable dependency/subprojects/cmlib/main.c)0
-rw-r--r--test cases/failing/114 cmake executable dependency/test.json (renamed from test cases/failing/113 cmake executable dependency/test.json)2
-rw-r--r--test cases/failing/115 allow_fallback with fallback/meson.build (renamed from test cases/failing/114 allow_fallback with fallback/meson.build)0
-rw-r--r--test cases/failing/115 allow_fallback with fallback/test.json (renamed from test cases/failing/114 allow_fallback with fallback/test.json)2
-rw-r--r--test cases/failing/116 nonsensical bindgen/meson.build (renamed from test cases/failing/115 nonsensical bindgen/meson.build)0
-rw-r--r--test cases/failing/116 nonsensical bindgen/src/header.h (renamed from test cases/failing/115 nonsensical bindgen/src/header.h)0
-rw-r--r--test cases/failing/116 nonsensical bindgen/src/source.c (renamed from test cases/failing/115 nonsensical bindgen/src/source.c)0
-rw-r--r--test cases/failing/116 nonsensical bindgen/test.json (renamed from test cases/failing/115 nonsensical bindgen/test.json)2
-rw-r--r--test cases/failing/117 run_target in test/meson.build (renamed from test cases/failing/116 run_target in test/meson.build)0
-rw-r--r--test cases/failing/117 run_target in test/test.json (renamed from test cases/failing/116 run_target in test/test.json)2
-rw-r--r--test cases/failing/117 run_target in test/trivial.c (renamed from test cases/failing/116 run_target in test/trivial.c)0
-rw-r--r--test cases/failing/118 run_target in add_install_script/meson.build (renamed from test cases/failing/117 run_target in add_install_script/meson.build)0
-rw-r--r--test cases/failing/118 run_target in add_install_script/test.json (renamed from test cases/failing/117 run_target in add_install_script/test.json)2
-rw-r--r--test cases/failing/118 run_target in add_install_script/trivial.c (renamed from test cases/failing/117 run_target in add_install_script/trivial.c)0
-rw-r--r--test cases/failing/119 pathsep in install_symlink/meson.build (renamed from test cases/failing/118 pathsep in install_symlink/meson.build)0
-rw-r--r--test cases/failing/119 pathsep in install_symlink/test.json (renamed from test cases/failing/118 pathsep in install_symlink/test.json)2
-rw-r--r--test cases/failing/120 subproject version conflict/meson.build4
-rw-r--r--test cases/failing/120 subproject version conflict/subprojects/A/meson.build4
-rw-r--r--test cases/failing/120 subproject version conflict/subprojects/B/meson.build3
-rw-r--r--test cases/failing/120 subproject version conflict/test.json7
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar1/baz.jpg (renamed from test cases/unit/98 install all targets/bar-notag.txt)0
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar1/baz.png.in (renamed from test cases/unit/98 install all targets/foo.in)0
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build8
-rw-r--r--test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build7
-rw-r--r--test cases/frameworks/10 gtk-doc/test.json2
-rw-r--r--test cases/frameworks/13 yelp/help/C/index2.page8
-rw-r--r--test cases/frameworks/13 yelp/help/C/index3.page8
-rw-r--r--test cases/frameworks/13 yelp/help/meson.build4
-rw-r--r--test cases/frameworks/13 yelp/test.json12
-rw-r--r--test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml4
-rw-r--r--test cases/frameworks/7 gnome/gdbus/meson.build19
-rw-r--r--test cases/frameworks/7 gnome/genmarshal/main.c.in (renamed from test cases/frameworks/7 gnome/genmarshal/main.c)8
-rw-r--r--test cases/frameworks/7 gnome/genmarshal/meson.build63
-rw-r--r--test cases/frameworks/7 gnome/test.json7
-rw-r--r--test cases/unit/100 custom target name/file.txt.in (renamed from test cases/unit/99 custom target name/file.txt.in)0
-rw-r--r--test cases/unit/100 custom target name/meson.build (renamed from test cases/unit/99 custom target name/meson.build)0
-rw-r--r--test cases/unit/100 custom target name/subdir/meson.build (renamed from test cases/unit/99 custom target name/subdir/meson.build)0
-rwxr-xr-xtest cases/unit/101 relative find program/foo.py (renamed from test cases/unit/99 relative find program/foo.py)0
-rw-r--r--test cases/unit/101 relative find program/meson.build (renamed from test cases/unit/99 relative find program/meson.build)0
-rw-r--r--test cases/unit/101 relative find program/subdir/meson.build (renamed from test cases/unit/99 relative find program/subdir/meson.build)0
-rw-r--r--test cases/unit/102 rlib linkage/lib2.rs (renamed from test cases/unit/100 rlib linkage/lib2.rs)0
-rw-r--r--test cases/unit/102 rlib linkage/main.rs (renamed from test cases/unit/100 rlib linkage/main.rs)0
-rw-r--r--test cases/unit/102 rlib linkage/meson.build (renamed from test cases/unit/100 rlib linkage/meson.build)0
-rw-r--r--test cases/unit/103 python without pkgconfig/meson.build (renamed from test cases/unit/101 python without pkgconfig/meson.build)0
-rw-r--r--test cases/unit/98 link full name/.gitignore (renamed from test cases/unit/97 link full name/.gitignore)0
-rw-r--r--test cases/unit/98 link full name/libtestprovider/meson.build (renamed from test cases/unit/97 link full name/libtestprovider/meson.build)0
-rw-r--r--test cases/unit/98 link full name/libtestprovider/provider.c (renamed from test cases/unit/97 link full name/libtestprovider/provider.c)0
-rw-r--r--test cases/unit/98 link full name/proguser/meson.build (renamed from test cases/unit/97 link full name/proguser/meson.build)0
-rw-r--r--test cases/unit/98 link full name/proguser/receiver.c (renamed from test cases/unit/97 link full name/proguser/receiver.c)0
-rw-r--r--test cases/unit/99 install all targets/bar-custom.txt (renamed from test cases/unit/98 install all targets/foo1-devel.h)0
-rw-r--r--test cases/unit/99 install all targets/bar-devel.h (renamed from test cases/unit/98 install all targets/subdir/bar2-devel.h)0
-rw-r--r--test cases/unit/99 install all targets/bar-notag.txt (renamed from test cases/unit/98 install all targets/subdir/foo2.in)0
-rw-r--r--test cases/unit/99 install all targets/custom_files/data.txt (renamed from test cases/unit/98 install all targets/custom_files/data.txt)0
-rw-r--r--test cases/unit/99 install all targets/foo.in (renamed from test cases/unit/98 install all targets/subdir/foo3-devel.h)0
-rw-r--r--test cases/unit/99 install all targets/foo1-devel.h0
-rw-r--r--test cases/unit/99 install all targets/lib.c (renamed from test cases/unit/98 install all targets/lib.c)0
-rw-r--r--test cases/unit/99 install all targets/main.c (renamed from test cases/unit/98 install all targets/main.c)0
-rw-r--r--test cases/unit/99 install all targets/meson.build (renamed from test cases/unit/98 install all targets/meson.build)0
-rw-r--r--test cases/unit/99 install all targets/script.py (renamed from test cases/unit/98 install all targets/script.py)0
-rw-r--r--test cases/unit/99 install all targets/subdir/bar2-devel.h0
-rw-r--r--test cases/unit/99 install all targets/subdir/foo2.in0
-rw-r--r--test cases/unit/99 install all targets/subdir/foo3-devel.h0
-rw-r--r--test cases/unit/99 install all targets/subdir/lib.c (renamed from test cases/unit/98 install all targets/subdir/lib.c)0
-rw-r--r--test cases/unit/99 install all targets/subdir/main.c (renamed from test cases/unit/98 install all targets/subdir/main.c)0
-rw-r--r--test cases/unit/99 install all targets/subdir/meson.build (renamed from test cases/unit/98 install all targets/subdir/meson.build)0
-rw-r--r--test cases/unit/99 install all targets/subdir/script.py (renamed from test cases/unit/98 install all targets/subdir/script.py)0
-rw-r--r--test cases/vala/11 generated vapi/libfoo/foo.metadata1
-rw-r--r--test cases/vala/11 generated vapi/libfoo/meson.build7
-rwxr-xr-xtools/dircondenser.py2
-rwxr-xr-xtools/gen_data.py140
-rw-r--r--unittests/allplatformstests.py18
-rw-r--r--unittests/baseplatformtests.py8
-rw-r--r--unittests/datatests.py36
-rw-r--r--unittests/helpers.py16
-rw-r--r--unittests/linuxliketests.py18
-rw-r--r--unittests/platformagnostictests.py4
-rw-r--r--unittests/rewritetests.py3
-rw-r--r--unittests/windowstests.py26
237 files changed, 2222 insertions, 2168 deletions
diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml
index 9dd1355..e5a1bd5 100644
--- a/.github/workflows/cygwin.yml
+++ b/.github/workflows/cygwin.yml
@@ -71,6 +71,13 @@ jobs:
vala
zlib-devel
+ - name: workaround wrong python version
+ run: |
+ export PATH=/usr/sbin:/usr/bin:/usr/local/bin:$(cygpath ${SYSTEMROOT})/system32
+ update-alternatives --verbose --set python /usr/bin/python3.8
+ update-alternatives --verbose --set python3 /usr/bin/python3.8
+ shell: C:\cygwin\bin\bash.exe --noprofile --norc -o igncr -eo pipefail '{0}'
+
- name: Run pip
run: |
export PATH=/usr/bin:/usr/local/bin:$(cygpath ${SYSTEMROOT})/system32
diff --git a/.github/workflows/lint_mypy.yml b/.github/workflows/lint.yml
index 195d733..cdfed11 100644
--- a/.github/workflows/lint_mypy.yml
+++ b/.github/workflows/lint.yml
@@ -1,30 +1,29 @@
-name: LintMypy
+name: Lint
concurrency:
- group: mypy-${{ github.head_ref }}
+ group: lint-${{ github.head_ref }}
cancel-in-progress: true
on:
push:
paths:
- "**.py"
- - ".github/workflows/lint_mypy.yml"
+ - ".github/workflows/lint.yml"
pull_request:
paths:
- "**.py"
- - ".github/workflows/lint_mypy.yml"
+ - ".github/workflows/lint.yml"
jobs:
- lint:
+ pylint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- # pylint version constraint can be removed when https://github.com/PyCQA/pylint/issues/3524 is resolved
- - run: python -m pip install pylint==2.4.4
+ - run: python -m pip install pylint
- run: pylint mesonbuild
custom_lint:
diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml
index a71ee33..e3d3821 100644
--- a/.github/workflows/website.yml
+++ b/.github/workflows/website.yml
@@ -61,4 +61,11 @@ jobs:
file: docs/_build/reference_manual.json
tag: ${{ github.ref }}
if: ${{ github.event_name == 'release' }}
+ - name: Release the current man docs
+ uses: svenstaro/upload-release-action@v2
+ with:
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ file: docs/_build/meson-reference.3
+ tag: ${{ github.ref }}
+ if: ${{ github.event_name == 'release' }}
diff --git a/README.md b/README.md
index aac22b0..342830f 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ build system.
#### Dependencies
- - [Python](https://python.org) (version 3.6 or newer)
+ - [Python](https://python.org) (version 3.7 or newer)
- [Ninja](https://ninja-build.org) (version 1.8.2 or newer)
#### Installing from source
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 2696fc1..2bdc65a 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -62,7 +62,7 @@ jobs:
steps:
- task: UsePythonVersion@0
inputs:
- versionSpec: '3.6'
+ versionSpec: '3.7'
addToPath: true
architecture: 'x64'
- task: PowerShell@2
diff --git a/ci/ciimage/bionic/install.sh b/ci/ciimage/bionic/install.sh
index 90858f0..74b407f 100755
--- a/ci/ciimage/bionic/install.sh
+++ b/ci/ciimage/bionic/install.sh
@@ -10,6 +10,7 @@ export DC=gdc
pkgs=(
python3-pip libxml2-dev libxslt1-dev libyaml-dev libjson-glib-dev
+ python3.7 python3.7-dev
wget unzip cmake doxygen
clang
pkg-config-arm-linux-gnueabihf
@@ -48,7 +49,13 @@ done
# packages
eatmydata apt-get -y install "${pkgs[@]}"
-install_python_packages
+# Actually select the right python version
+update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1 \
+ --slave /usr/lib/x86_64-linux-gnu/pkgconfig/python3.pc python3.pc /usr/lib/x86_64-linux-gnu/pkgconfig/python-3.6.pc
+update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 2 \
+ --slave /usr/lib/x86_64-linux-gnu/pkgconfig/python3.pc python3.pc /usr/lib/x86_64-linux-gnu/pkgconfig/python-3.7.pc
+
+python3 -m pip install -U "${base_python_pkgs[@]}" "${python_pkgs[@]}"
# Install the ninja 0.10
wget https://github.com/ninja-build/ninja/releases/download/v1.10.0/ninja-linux.zip
diff --git a/ci/run.ps1 b/ci/run.ps1
index 33a01fe..ddbf3d1 100644
--- a/ci/run.ps1
+++ b/ci/run.ps1
@@ -20,7 +20,7 @@ if ($env:arch -eq 'x64') {
# Rust puts its shared stdlib in a secret place, but it is needed to run tests.
$env:Path += ";$HOME/.rustup/toolchains/stable-i686-pc-windows-msvc/bin"
# Need 32-bit Python for tests that need the Python dependency
- $env:Path = "C:\hostedtoolcache\windows\Python\3.6.8\x86;C:\hostedtoolcache\windows\Python\3.6.8\x86\Scripts;$env:Path"
+ $env:Path = "C:\hostedtoolcache\windows\Python\3.7.9\x86;C:\hostedtoolcache\windows\Python\3.7.9\x86\Scripts;$env:Path"
}
# Set the CI env var for the meson test framework
diff --git a/docs/markdown/Continuous-Integration.md b/docs/markdown/Continuous-Integration.md
index f24bdb0..ec0b4e0 100644
--- a/docs/markdown/Continuous-Integration.md
+++ b/docs/markdown/Continuous-Integration.md
@@ -207,7 +207,7 @@ GCC on Linux, Mac and Windows. The optional `on:` parameters only run
this CI when the C code is changed--corresponding ci_python.yml might
run only on "**.py" file changes.
-```yml
+```yaml
name: ci_meson
on:
diff --git a/docs/markdown/Getting-meson.md b/docs/markdown/Getting-meson.md
index ec6f1c6..c3c3cc8 100644
--- a/docs/markdown/Getting-meson.md
+++ b/docs/markdown/Getting-meson.md
@@ -1,6 +1,6 @@
# Getting Meson
-Meson is implemented in Python 3, and requires 3.6 or newer. If your
+Meson is implemented in Python 3, and requires 3.7 or newer. If your
operating system provides a package manager, you should install it
with that. For platforms that don't have a package manager, you need
to download it from [Python's home page]. See below for
@@ -14,7 +14,7 @@ itself without doing anything special.
On Windows, if you did not install Python with the installer options
that make Python scripts executable, you will have to run `python
-/path/to/meson.py`, where `python` is Python 3.6 or newer.
+/path/to/meson.py`, where `python` is Python 3.7 or newer.
The newest development code can be obtained directly from [Git], and
we strive to ensure that it will always be working and usable. All
diff --git a/docs/markdown/Getting-meson_ptbr.md b/docs/markdown/Getting-meson_ptbr.md
index b5af345..f4f3ac1 100644
--- a/docs/markdown/Getting-meson_ptbr.md
+++ b/docs/markdown/Getting-meson_ptbr.md
@@ -1,6 +1,6 @@
# Obtendo o Meson
-Meson é implementado em Python 3, e requer a versão 3.6 ou mais nova.
+Meson é implementado em Python 3, e requer a versão 3.7 ou mais nova.
se o seu sistema operacional provê um gerenciador de pacotes, você deve
instalar o Meson com ele. Para plataformas que não tem um gerenciador de
pacotes, você precisa baixa-lo da [página inicial do Python]. Veja abaixo
@@ -14,7 +14,7 @@ do git sem fazer nada de especial.
No Windows, se você não instalar o Python com a opção do instalador que fazem
os *scripts* Python executáveis, você vai ter que executar `python
-/path/to/meson.py`, onde `python` é o Python 3.6 ou mais novo.
+/path/to/meson.py`, onde `python` é o Python 3.7 ou mais novo.
O código de desenvolvimento mais recente pode ser obtido diretamente do [Git],
e nós lutamos para garatir que ele vai estar sempre funcionando e usável. Todos
diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md
index 4f08c6d..616562a 100644
--- a/docs/markdown/Gnome-module.md
+++ b/docs/markdown/Gnome-module.md
@@ -133,8 +133,7 @@ argument is the basename of the output files.
* `nostdinc`: if true, don't include the standard marshallers from glib
* `prefix`: the prefix to use for symbols
* `skip_source`: if true, skip source location comments
-* `sources` []str *required*: List of string sources to consume
-* `sources`: the list of sources to use as inputs
+* `sources` [](str | File) *required*: the list of sources to use as inputs
* `stdinc`: if true, include the standard marshallers from glib
* `valist_marshallers`: if true, generate va_list marshallers
@@ -321,8 +320,8 @@ VAPI or Vala binaries.
languages: []string, symlink_media: bool = true): void
```
-Installs help documentation using Yelp. The first argument is the
-project id.
+Installs help documentation for Yelp using itstool and gettext. The first
+argument is the project id.
Additionally, sources can be passed as additional positional arguments. This
was, however, undocumented and never officially supported. Due to a longstanding
diff --git a/docs/markdown/RPM-module.md b/docs/markdown/RPM-module.md
deleted file mode 100644
index cab6d96..0000000
--- a/docs/markdown/RPM-module.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# RPM module
-
-The RPM module can be used to create a sample rpm spec file for a
-Meson project. It autodetects installed files, dependencies and so
-on. Using it is very simple. At the very end of your Meson project
-(that is, the end of your top level `meson.build` file) add these two
-lines.
-
-```meson
-rpm = import('rpm')
-rpm.generate_spec_template()
-```
-
-Run Meson once on your code and the template will be written in your
-build directory. Then remove the two lines above and manually edit the
-template to add missing information. After this it is ready for use.
diff --git a/docs/markdown/Release-notes-for-0.61.0.md b/docs/markdown/Release-notes-for-0.61.0.md
new file mode 100644
index 0000000..8798453
--- /dev/null
+++ b/docs/markdown/Release-notes-for-0.61.0.md
@@ -0,0 +1,138 @@
+---
+title: Release 0.61.0
+short-description: Release notes for 0.61.0
+...
+
+# New features
+
+## backend_startup_project
+
+`backend_startup_project` will no longer erase the last project in a VS
+solution if it is not the specified project.
+
+## Windows.compile_resources CustomTarget
+
+Previously the Windows module only accepted CustomTargets with one output, it
+now accepts them with more than one output, and creates a windows resource
+target for each output. Additionally it now accepts indexes of CustomTargets
+
+```meson
+
+ct = custom_target(
+ 'multiple',
+ output : ['resource', 'another resource'],
+ ...
+)
+
+ct2 = custom_target(
+ 'slice',
+ output : ['resource', 'not a resource'],
+ ...
+)
+
+resources = windows.compile_resources(ct, ct2[0])
+```
+
+## Add a man page backend to refman
+
+The refman docs (function and object reference) can now be generated as a man
+page.
+
+## ``extract_objects()`` supports generated sources
+
+Custom targets or generated files (returned by ``generator.process()``)
+can now be passed to ``extract_objects()``.
+
+## Python 3.6 support will be dropped in the next release
+
+The final [Python 3.6 release was 3.6.15 in September](https://www.python.org/dev/peps/pep-0494/#lifespan).
+This release series is now End-of-Life (EOL). The only LTS distribution that
+still ships Python 3.5 as the default Python is Ubuntu 18.04, which has Python
+3.8 available as well.
+
+Python 3.7 has various features that we find useful such as future annotations,
+the importlib.resources module, and dataclasses.
+
+As a result, we will begin requiring Python 3.7 or newer in Meson 0.62, which
+is the next release. Starting with Meson 0.61, we now print a `NOTICE:` when
+a `meson` command is run on Python 3.6 to inform users about this.
+
+## Warning if check kwarg of run_command is missing
+
+The `check` kwarg of `run_command` currently defaults to `false`.
+Because we want to change that, running
+```meson
+run_command('cmd')
+```
+now results in:
+```text
+WARNING: You should add the boolean check kwarg to the run_command call.
+ It currently defaults to false,
+ but it will default to true in future releases of meson.
+ See also: https://github.com/mesonbuild/meson/issues/9300
+```
+
+## `meson rewrite` can modify `extra_files`
+
+The build script rewriter can now modify targets' `extra_files` lists,
+or create them if absent. It it used in the same way as with rewriting
+source lists:
+
+```bash
+meson rewrite target <target name/id> {add_extra_files/rm_extra_files} [list of extra files]
+```
+
+The rewriter's script mode also supports these actions:
+
+```json
+{
+ "type": "target",
+ "target": "<target name>",
+ "operation": "extra_files_add / extra_files_rm",
+ "sources": ["list", "of", "extra", "files", "to", "add, remove"],
+}
+```
+
+## `meson rewrite target <target> info` outputs *target*'s `extra_files`
+
+Targets' `extra_files` lists are now included in the rewriter's target info dump
+as a list of file paths, in the same way `sources` are. This applies to both
+`meson rewrite` CLI and script mode.
+
+## Visual Studio 2022 backend
+
+As Visual Studio 2022 is released recently, it's time to support the
+new version in Meson. This mainly includes the new "v143" platform tools.
+
+The usage is similar to other backends. For example
+```meson
+meson setup builddir --backend=vs2022
+```
+will configure "builddir" for projects compatible with Visual Studio 2022.
+
+## Support for CMake <3.14 is now deprecated for CMake subprojects
+
+In CMake 3.14, the File API was introduced and the old CMake server API was
+deprecated (and removed in CMake 3.20). Thus support for this API will also
+be removed from Meson in future releases.
+
+This deprecation only affects CMake subprojects.
+
+## Added support for sccache
+
+Meson now supports [sccache](https://github.com/mozilla/sccache) just
+like it has supported CCache. If both sccache and CCache are
+available, the autodetection logic prefers sccache.
+
+## install_symlink function
+
+It is now possible to request for symbolic links to be installed during
+installation. The `install_symlink` function takes a positional argument to
+the link name, and installs a symbolic link pointing to `pointing_to` target.
+The link will be created under `install_dir` directory and cannot contain path
+separators.
+
+```meson
+install_symlink('target', pointing_to: '../bin/target', install_dir: '/usr/sbin')
+```
+
diff --git a/docs/markdown/Running-Meson.md b/docs/markdown/Running-Meson.md
index 2873cbc..2bc0b9b 100644
--- a/docs/markdown/Running-Meson.md
+++ b/docs/markdown/Running-Meson.md
@@ -31,7 +31,7 @@ meson setup builddir
We invoke Meson with the `setup` command, giving it the location of the build
directory. Meson uses [out of source
-builds](http://voices.canonical.com/jussi.pakkanen/2013/04/16/why-you-should-consider-using-separate-build-directories/).
+builds](http://web.archive.org/web/20190715081007/http://voices.canonical.com/jussi.pakkanen/2013/04/16/why-you-should-consider-using-separate-build-directories/).
Hint: The syntax of Meson is `meson [command] [arguments] [options]`.
The `setup` command takes a `builddir` and a `srcdir` argument. If no
diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md
index 9f8b09b..54834b7 100644
--- a/docs/markdown/Rust-module.md
+++ b/docs/markdown/Rust-module.md
@@ -34,7 +34,7 @@ that automatically.
Additional, test only dependencies may be passed via the dependencies
argument.
-### bindgen(*, input: string | BuildTarget | []string | []BuildTarget, output: string, include_directories: []include_directories, c_args: []string, args: []string)
+### bindgen(*, input: string | BuildTarget | [](string | BuildTarget), output: string, include_directories: []include_directories, c_args: []string, args: []string)
This function wraps bindgen to simplify creating rust bindings around C
libraries. This has two advantages over hand-rolling ones own with a
@@ -60,8 +60,8 @@ rust = import('unstable-rust')
inc = include_directories('..'¸ '../../foo')
generated = rust.bindgen(
- 'myheader.h',
- 'generated.rs',
+ input : 'myheader.h',
+ output : 'generated.rs',
include_directories : [inc, include_directories('foo')],
args : ['--no-rustfmt-bindings'],
c_args : ['-DFOO=1'],
@@ -77,7 +77,7 @@ h1 = custom_target(...)
h2 = custom_target(...)
r1 = rust.bindgen(
- [h1, h2], # h1 includes h2,
- 'out.rs',
+ input : [h1, h2], # h1 includes h2,
+ output : 'out.rs',
)
```
diff --git a/docs/markdown/Subprojects.md b/docs/markdown/Subprojects.md
index 7cb04e0..fef9d11 100644
--- a/docs/markdown/Subprojects.md
+++ b/docs/markdown/Subprojects.md
@@ -153,7 +153,7 @@ Because this is such a common operation, Meson provides a shortcut for
this use case.
```meson
-dep = dependency('foo', fallback : [subproject_name, variable_name])
+dep = dependency('foo', fallback : ['subproject_name', 'variable_name'])
```
The `fallback` keyword argument takes two items, the name of the
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index bd146d7..8510d6e 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -94,7 +94,7 @@ format files
- [Libvirt](https://libvirt.org), a toolkit to manage virtualization platforms
- [Libzim](https://github.com/openzim/libzim), the reference implementation for the ZIM file format
- [Marker](https://github.com/fabiocolacio/Marker), a GTK-3 markdown editor
- - [Mesa](https://gitlab.freedesktop.org/mesa/mesa/), an open source graphics driver project
+ - [Mesa](https://mesa3d.org/), an open source graphics driver project
- [MiracleCast](https://github.com/albfan/miraclecast), connect external monitors to your system via Wifi-Display specification aka Miracast
- [mpv](https://github.com/mpv-player/mpv), a free, open source, and cross-platform media player
- [mrsh](https://github.com/emersion/mrsh), a minimal POSIX shell
diff --git a/docs/markdown/fallback-wraptool.md b/docs/markdown/fallback-wraptool.md
deleted file mode 100644
index d4f5af2..0000000
--- a/docs/markdown/fallback-wraptool.md
+++ /dev/null
@@ -1,43 +0,0 @@
----
-title: fallback wraptool
-...
-
-# In case of emergency
-
-In case wraptool is down we have created a backup script that you can
-use to download wraps directly from the GitHub repos. It is not as
-slick and may have bugs but at least it will allow you to use wraps.
-
-## Using it
-
-To list all available wraps:
-
- ghwt.py list
-
-To install a wrap, go to your source root, make sure that the
-`subprojects` directory exists and run this command:
-
- ghwt.py install <projectname> [<branchname>]
-
-This will stage the subproject ready to use. If you have multiple
-subprojects you need to download them all manually.
-
-Specifying branch name is optional. If not specified, the list of
-potential branches is sorted alphabetically and the last branch is
-used.
-
-*Note* The tool was added in 0.32.0, for versions older than that you
-need to delete the `foo.wrap` file to work around this issue.
-
-## How to upgrade an existing dir/fix broken state/any other problem
-
-Nuke the contents of `subprojects` and start again.
-
-## Known issues
-
-Some repositories show up in the list but are not installable. They
-would not show up in the real WrapDB because they are works in
-progress.
-
-GitHub web API limits the amount of queries you can do to 60/hour. If
-you exceed that you need to wait for the timer to reset.
diff --git a/docs/markdown/index.md b/docs/markdown/index.md
index 14bdfbe..427cc05 100644
--- a/docs/markdown/index.md
+++ b/docs/markdown/index.md
@@ -31,14 +31,16 @@ read [this beginner guide](SimpleStart.md) to get started.
## Community
-There are two main methods of connecting with other Meson
-developers. The easiest way for most people is a web chat. The channel
-to use is `#mesonbuild` either via Matrix ([web
+The easiest way for most people to connect to other Meson developers is
+a web chat. The channel to use is `#mesonbuild` either via Matrix ([web
interface](https://app.element.io/#/room/#mesonbuild:matrix.org)) or
[OFTC IRC](https://www.oftc.net/).
-The second one is the mailing list, which is hosted at
-[Google Groups](https://groups.google.com/forum/#!forum/mesonbuild).
+Other methods of communication include the [mailing
+list](https://groups.google.com/forum/#!forum/mesonbuild) (hosted by
+Google Groups) and the
+[Discussions](https://github.com/mesonbuild/meson/discussions) section
+of the Meson GitHub repository.
### [Projects using Meson](Users.md)
diff --git a/docs/markdown/snippets/about_minimum_python_version.md b/docs/markdown/snippets/about_minimum_python_version.md
new file mode 100644
index 0000000..fa44a75
--- /dev/null
+++ b/docs/markdown/snippets/about_minimum_python_version.md
@@ -0,0 +1,7 @@
+## Minimum required Python version updated to 3.7
+
+Meson now requires at least Python version 3.7 to run as Python 3.6 reached EOL
+on December 2021. In practice this should only affect people developing on
+Ubuntu Bionic, who will need to manually install python3.8 from the official
+repositories.
+
diff --git a/docs/markdown/snippets/armclang-support.md b/docs/markdown/snippets/armclang-support.md
new file mode 100644
index 0000000..80e7af2
--- /dev/null
+++ b/docs/markdown/snippets/armclang-support.md
@@ -0,0 +1,6 @@
+## Support for ARM Ltd. Clang toolchain
+
+Support for the `armltdclang` compiler has been added. This differs from the
+existing `armclang` toolchain in that it is a fork of Clang by ARM Ltd. and
+supports native compilation. The Keil `armclang` toolchain only supports
+cross-compilation to embedded devices.
diff --git a/docs/markdown/snippets/check_false_warning.md b/docs/markdown/snippets/check_false_warning.md
deleted file mode 100644
index 50214b7..0000000
--- a/docs/markdown/snippets/check_false_warning.md
+++ /dev/null
@@ -1,14 +0,0 @@
-## Warning if check kwarg of run_command is missing
-
-The `check` kwarg of `run_command` currently defaults to `false`.
-Because we want to change that, running
-```meson
-run_command('cmd')
-```
-now results in:
-```text
-WARNING: You should add the boolean check kwarg to the run_command call.
- It currently defaults to false,
- but it will default to true in future releases of meson.
- See also: https://github.com/mesonbuild/meson/issues/9300
-```
diff --git a/docs/markdown/snippets/cmake_deprecated.md b/docs/markdown/snippets/cmake_deprecated.md
deleted file mode 100644
index 9e456e7..0000000
--- a/docs/markdown/snippets/cmake_deprecated.md
+++ /dev/null
@@ -1,7 +0,0 @@
-## Support for CMake <3.14 is now deprecated for CMake subprojects
-
-In CMake 3.14, the File API was introduced and the old CMake server API was
-deprecated (and removed in CMake 3.20). Thus support for this API will also
-be removed from Meson in future releases.
-
-This deprecation only affects CMake subprojects.
diff --git a/docs/markdown/snippets/extract-more-objects.md b/docs/markdown/snippets/extract-more-objects.md
deleted file mode 100644
index 73a4757..0000000
--- a/docs/markdown/snippets/extract-more-objects.md
+++ /dev/null
@@ -1,4 +0,0 @@
-## ``extract_objects()`` supports generated sources
-
-Custom targets or generated files (returned by ``generator.process()``)
-can now be passed to ``extract_objects()``.
diff --git a/docs/markdown/snippets/fix_backend_startup_project.md b/docs/markdown/snippets/fix_backend_startup_project.md
deleted file mode 100644
index 8269ef6..0000000
--- a/docs/markdown/snippets/fix_backend_startup_project.md
+++ /dev/null
@@ -1,4 +0,0 @@
-## backend_startup_project
-
-`backend_startup_project` will no longer erase the last project in a VS
-solution if it is not the specified project.
diff --git a/docs/markdown/snippets/install_symlink.md b/docs/markdown/snippets/install_symlink.md
deleted file mode 100644
index 752c422..0000000
--- a/docs/markdown/snippets/install_symlink.md
+++ /dev/null
@@ -1,11 +0,0 @@
-## install_symlink function
-
-It is now possible to request for symbolic links to be installed during
-installation. The `install_symlink` function takes a positional argument to
-the link name, and installs a symbolic link pointing to `pointing_to` target.
-The link will be created under `install_dir` directory and cannot contain path
-separators.
-
-```meson
-install_symlink('target', pointing_to: '../bin/target', install_dir: '/usr/sbin')
-```
diff --git a/docs/markdown/snippets/removing_rpm_module.md b/docs/markdown/snippets/removing_rpm_module.md
new file mode 100644
index 0000000..c492d51
--- /dev/null
+++ b/docs/markdown/snippets/removing_rpm_module.md
@@ -0,0 +1,10 @@
+## Removal of the RPM module
+
+Due to lack of interest, lack of maintainership, and lack of a clear purpose,
+the RPM module has been removed.
+
+Users interested in one-shot tools to generate an RPM spec file template for
+distro packaging, are encouraged develop an external tool that reads the
+introspection data.
+
+For more details, see https://github.com/mesonbuild/meson/issues/9764
diff --git a/docs/markdown/snippets/rewriter_extra_files.md b/docs/markdown/snippets/rewriter_extra_files.md
deleted file mode 100644
index c46f076..0000000
--- a/docs/markdown/snippets/rewriter_extra_files.md
+++ /dev/null
@@ -1,26 +0,0 @@
-## `meson rewrite` can modify `extra_files`
-
-The build script rewriter can now modify targets' `extra_files` lists,
-or create them if absent. It it used in the same way as with rewriting
-source lists:
-
-```bash
-meson rewrite target <target name/id> {add_extra_files/rm_extra_files} [list of extra files]
-```
-
-The rewriter's script mode also supports these actions:
-
-```json
-{
- "type": "target",
- "target": "<target name>",
- "operation": "extra_files_add / extra_files_rm",
- "sources": ["list", "of", "extra", "files", "to", "add, remove"],
-}
-```
-
-## `meson rewrite target <target> info` outputs *target*'s `extra_files`
-
-Targets' `extra_files` lists are now included in the rewriter's target info dump
-as a list of file paths, in the same way `sources` are. This applies to both
-`meson rewrite` CLI and script mode.
diff --git a/docs/markdown/snippets/sccache.md b/docs/markdown/snippets/sccache.md
deleted file mode 100644
index 72bdf5f..0000000
--- a/docs/markdown/snippets/sccache.md
+++ /dev/null
@@ -1,5 +0,0 @@
-## Added support for sccache
-
-Meson now supports [sccache](https://github.com/mozilla/sccache) just
-like it has supported CCache. If both sccache and CCache are
-available, the autodetection logic prefers sccache.
diff --git a/docs/markdown/snippets/vs_2022.md b/docs/markdown/snippets/vs_2022.md
deleted file mode 100644
index 0c3ff02..0000000
--- a/docs/markdown/snippets/vs_2022.md
+++ /dev/null
@@ -1,10 +0,0 @@
-## Visual Studio 2022 backend
-
-As Visual Studio 2022 is released recently, it's time to support the
-new version in Meson. This mainly includes the new "v143" platform tools.
-
-The usage is similar to other backends. For example
-```meson
-meson setup builddir --backend=vs2022
-```
-will configure "builddir" for projects compatible with Visual Studio 2022.
diff --git a/docs/markdown/snippets/windows_custom_targets.md b/docs/markdown/snippets/windows_custom_targets.md
deleted file mode 100644
index cbc2f9d..0000000
--- a/docs/markdown/snippets/windows_custom_targets.md
+++ /dev/null
@@ -1,22 +0,0 @@
-## Windows.compile_resources CustomTarget
-
-Previously the Windows module only accepted CustomTargets with one output, it
-now accepts them with more than one output, and creates a windows resource
-target for each output. Additionally it now accepts indexes of CustomTargets
-
-```meson
-
-ct = custom_target(
- 'multiple',
- output : ['resource', 'another resource'],
- ...
-)
-
-ct2 = custom_target(
- 'slice',
- output : ['resource', 'not a resource'],
- ...
-)
-
-resources = windows.compile_resources(ct, ct2[0])
-```
diff --git a/docs/meson.build b/docs/meson.build
index 53d4392..00e90ed 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -63,6 +63,22 @@ refman_json = custom_target(
],
)
+refman_man = custom_target(
+ 'gen_refman_man',
+ build_by_default: true,
+ input: refman_binary,
+ output: 'meson-reference.3',
+ command: [
+ genrefman,
+ '-l', 'pickle',
+ '-g', 'man',
+ '-i', '@INPUT@',
+ '-o', '@OUTPUT@',
+ '--force-color',
+ '--no-modules',
+ ],
+)
+
test('validate_docs', find_program('./jsonvalidator.py'), args: [refman_json])
hotdoc_prog = find_program('hotdoc', version: '>=0.13.7')
diff --git a/docs/refman/generatorbase.py b/docs/refman/generatorbase.py
index e93166f..08ce492 100644
--- a/docs/refman/generatorbase.py
+++ b/docs/refman/generatorbase.py
@@ -43,6 +43,11 @@ class GeneratorBase(metaclass=ABCMeta):
return f'0_{fn.name}'
return sorted([x for x in raw if not x.hidden], key=key_fn)
+ @staticmethod
+ def _extract_meson_version() -> str:
+ from mesonbuild.coredata import version
+ return version
+
@property
def functions(self) -> T.List[Function]:
return GeneratorBase.sorted_and_filtered(self.manual.functions)
diff --git a/docs/refman/generatorjson.py b/docs/refman/generatorjson.py
index f5164d4..9f92342 100644
--- a/docs/refman/generatorjson.py
+++ b/docs/refman/generatorjson.py
@@ -92,13 +92,6 @@ class GeneratorJSON(GeneratorBase):
'methods': {x.name: self._generate_function(x) for x in self.sorted_and_filtered(obj.methods)},
}
- def _extract_meson_version(self) -> str:
- # Hack around python relative imports to get to the Meson version
- import sys
- sys.path.append(Path(__file__).resolve().parents[2].as_posix())
- from mesonbuild.coredata import version
- return version
-
def generate(self) -> None:
data: J.Root = {
'version_major': J.VERSION_MAJOR,
diff --git a/docs/refman/generatorman.py b/docs/refman/generatorman.py
new file mode 100644
index 0000000..dfd211f
--- /dev/null
+++ b/docs/refman/generatorman.py
@@ -0,0 +1,382 @@
+import re
+from pathlib import Path
+
+from .generatorbase import GeneratorBase
+from .model import (
+ ReferenceManual,
+ Function,
+ Object,
+ PosArg,
+ VarArgs,
+ Kwarg,
+)
+
+import typing as T
+
+
+class ManPage:
+ def __init__(self, path: Path):
+ self.path = path
+ self.text = ""
+
+ def reset_font(self) -> None:
+ self.text += ".P\n"
+
+ def title(self, name: str, section: int) -> None:
+ import datetime
+
+ date = datetime.date.today()
+ self.reset_font()
+ self.text += f'.TH "{name}" "{section}" "{date}"\n'
+
+ def section(self, name: str) -> None:
+ self.reset_font()
+ self.text += f".SH {name}\n"
+
+ def subsection(self, name: str) -> None:
+ self.reset_font()
+ self.text += f".SS {name}\n"
+
+ def par(self, text: str) -> None:
+ self.reset_font()
+ self.text += f"{text}\n"
+
+ def indent(self, amount: int = 4) -> None:
+ self.text += f".RS {amount}\n"
+
+ def unindent(self) -> None:
+ self.text += ".RE\n"
+
+ def br(self) -> None:
+ self.text += ".br\n"
+
+ def nl(self) -> None:
+ self.text += "\n"
+
+ def line(self, text: str) -> None:
+ if text and text[0] in [".", "'"]:
+ self.text += "\\"
+ self.text += f"{text}\n"
+
+ def inline(self, text: str) -> None:
+ self.text += f"{text}"
+
+ def write(self) -> None:
+ self.path.write_text(self.text, encoding="utf-8")
+
+ @staticmethod
+ def bold(text: str) -> str:
+ return f"\\fB{text}\\fR"
+
+ @staticmethod
+ def italic(text: str) -> str:
+ return f"\\fI{text}\\fR"
+
+
+class GeneratorMan(GeneratorBase):
+ def __init__(
+ self, manual: ReferenceManual, out: Path, enable_modules: bool
+ ) -> None:
+ super().__init__(manual)
+ self.out = out
+ self.enable_modules = enable_modules
+ self.links: T.List[str] = []
+
+ def generate_description(self, page: ManPage, desc: str) -> None:
+ def italicise(match: T.Match[str]) -> str:
+ v = match.group(1)
+ if v[0] == "@":
+ v = v[1:]
+
+ return ManPage.italic(v)
+
+ desc = re.sub(re.compile(r"\[\[(.*?)\]\]", re.DOTALL), italicise, desc)
+
+ def linkify(match: T.Match[str]) -> str:
+ replacement = ManPage.italic(match.group(1))
+
+ if match.group(2)[0] != "#":
+ if match.group(2) in self.links:
+ num = self.links.index(match.group(2))
+ else:
+ self.links.append(match.group(2))
+ num = len(self.links)
+
+ replacement += f"[{num}]"
+
+ return replacement
+
+ desc = re.sub(re.compile(r"\[(.*?)\]\((.*?)\)", re.DOTALL), linkify, desc)
+
+ def bold(match: T.Match[str]) -> str:
+ return ManPage.bold(match.group(1))
+
+ desc = re.sub(re.compile(r"\*(.*?)\*"), bold, desc)
+
+ isCode = False
+ for chunk in desc.split("```"):
+ if isCode:
+ page.indent()
+ lines = chunk.strip().split("\n")
+ if lines[0] == "meson":
+ lines = lines[1:]
+
+ for line in lines:
+ page.line(line)
+ page.br()
+ page.unindent()
+ else:
+ inList = False
+ for line in chunk.strip().split("\n"):
+ if len(line) == 0:
+ page.nl()
+ if inList:
+ page.nl()
+ inList = False
+ elif line[0:2] in ["- ", "* "]:
+ if inList:
+ page.nl()
+ page.br()
+ else:
+ inList = True
+
+ page.inline(line.strip() + " ")
+ elif inList and line[0] == " ":
+ page.inline(line.strip() + " ")
+ else:
+ inList = False
+ page.line(line)
+
+ if inList:
+ page.nl()
+
+ isCode = not isCode
+
+ def function_name(self, f: Function, o: Object = None) -> str:
+ name = ""
+ if o is not None:
+ name += f"{o.name}."
+
+ name += f.name
+ return name
+
+ def generate_function_signature(
+ self, page: ManPage, f: Function, o: Object = None
+ ) -> None:
+ args = []
+
+ if f.posargs:
+ args += [arg.name for arg in f.posargs]
+
+ if f.varargs:
+ args += [f.varargs.name + "..."]
+
+ if f.optargs:
+ args += [f"[{arg.name}]" for arg in f.optargs]
+
+ for kwarg in self.sorted_and_filtered(list(f.kwargs.values())):
+ kw = kwarg.name + ":"
+ if kwarg.default:
+ kw += " " + ManPage.bold(kwarg.default)
+ args += [kw]
+
+ ret = ManPage.italic(f.returns.raw) + " "
+
+ prefix = f"{ret}{self.function_name(f, o)}("
+ sig = ", ".join(args)
+ suffix = ")"
+
+ if len(prefix) + len(sig) + len(suffix) > 70:
+ page.line(prefix)
+ page.br()
+ page.indent()
+ for arg in args:
+ page.line(arg + ",")
+ page.br()
+ page.unindent()
+ page.line(suffix)
+ else:
+ page.line(prefix + sig + suffix)
+
+ def base_info(
+ self, x: T.Union[PosArg, VarArgs, Kwarg, Function, Object]
+ ) -> T.List[str]:
+ info = []
+ if x.deprecated:
+ info += [ManPage.bold("deprecated") + f" since {x.deprecated}"]
+ if x.since:
+ info += [f"since {x.since}"]
+
+ return info
+
+ def generate_function_arg(
+ self,
+ page: ManPage,
+ arg: T.Union[PosArg, VarArgs, Kwarg],
+ isOptarg: bool = False,
+ ) -> None:
+ required = (
+ arg.required
+ if isinstance(arg, Kwarg)
+ else not isOptarg and not isinstance(arg, VarArgs)
+ )
+
+ page.line(ManPage.bold(arg.name))
+
+ info = [ManPage.italic(arg.type.raw)]
+
+ if required:
+ info += [ManPage.bold("required")]
+ if isinstance(arg, (PosArg, Kwarg)) and arg.default:
+ info += [f"default: {arg.default}"]
+ if isinstance(arg, VarArgs):
+ mn = 0 if arg.min_varargs < 0 else arg.min_varargs
+ mx = "N" if arg.max_varargs < 0 else arg.max_varargs
+ info += [f"{mn}...{mx} times"]
+
+ info += self.base_info(arg)
+
+ page.line(", ".join(info))
+
+ page.br()
+ page.indent(2)
+ self.generate_description(page, arg.description.strip())
+ page.unindent()
+ page.nl()
+
+ def generate_function_argument_section(
+ self,
+ page: ManPage,
+ name: str,
+ args: T.Sequence[T.Union[PosArg, VarArgs, Kwarg]],
+ isOptarg: bool = False,
+ ) -> None:
+ if not args:
+ return
+
+ page.line(ManPage.bold(name))
+ page.indent()
+ for arg in args:
+ self.generate_function_arg(page, arg, isOptarg)
+ page.unindent()
+
+ def generate_sub_sub_section(
+ self, page: ManPage, name: str, text: T.List[str], process: bool = True
+ ) -> None:
+ page.line(ManPage.bold(name))
+ page.indent()
+ if process:
+ for line in text:
+ self.generate_description(page, line.strip())
+ else:
+ page.line("\n\n".join([line.strip() for line in text]))
+ page.unindent()
+
+ def generate_function(self, page: ManPage, f: Function, obj: Object = None) -> None:
+ page.subsection(self.function_name(f, obj) + "()")
+ page.indent(0)
+
+ page.line(ManPage.bold("SYNOPSIS"))
+ page.indent()
+ self.generate_function_signature(page, f, obj)
+
+ info = self.base_info(f)
+ if info:
+ page.nl()
+ page.line(", ".join(info))
+ page.unindent()
+ page.nl()
+
+ self.generate_sub_sub_section(page, "DESCRIPTION", [f.description])
+ page.nl()
+
+ self.generate_function_argument_section(page, "POSARGS", f.posargs)
+ if f.varargs:
+ self.generate_function_argument_section(page, "VARARGS", [f.varargs])
+ self.generate_function_argument_section(page, "OPTARGS", f.optargs, True)
+ self.generate_function_argument_section(
+ page, "KWARGS", self.sorted_and_filtered(list(f.kwargs.values()))
+ )
+
+ if f.notes:
+ self.generate_sub_sub_section(page, "NOTES", f.notes)
+ if f.warnings:
+ self.generate_sub_sub_section(page, "WARNINGS", f.warnings)
+ if f.example:
+ self.generate_sub_sub_section(page, "EXAMPLE", [f.example])
+
+ page.unindent()
+
+ def generate_object(self, page: ManPage, obj: Object) -> None:
+ page.subsection(obj.name)
+ page.indent(2)
+
+ info = self.base_info(obj)
+ if info:
+ page.line(", ".join(info))
+ page.br()
+
+ if obj.extends:
+ page.line(ManPage.bold("extends: ") + obj.extends)
+ page.br()
+
+ ret = [x.name for x in self.sorted_and_filtered(obj.returned_by)]
+ if ret:
+ page.line(ManPage.bold("returned_by: ") + ", ".join(ret))
+ page.br()
+
+ ext = [x.name for x in self.sorted_and_filtered(obj.extended_by)]
+ if ext:
+ page.line(ManPage.bold("extended_by: ") + ", ".join(ext))
+ page.br()
+
+ page.nl()
+
+ self.generate_description(page, obj.description.strip())
+ page.nl()
+
+ if obj.notes:
+ self.generate_sub_sub_section(page, "NOTES", obj.notes)
+ if obj.warnings:
+ self.generate_sub_sub_section(page, "WARNINGS", obj.warnings)
+ if obj.example:
+ self.generate_sub_sub_section(page, "EXAMPLE", [obj.example])
+
+ page.unindent()
+
+ def generate(self) -> None:
+ page = ManPage(self.out)
+
+ page.title("meson-reference", 3)
+
+ page.section("NAME")
+ page.par(
+ f"meson-reference v{self._extract_meson_version()}"
+ + " - a reference for meson functions and objects"
+ )
+
+ page.section("DESCRIPTION")
+ self.generate_description(
+ page,
+ """This manual is divided into two sections, *FUNCTIONS* and *OBJECTS*. *FUNCTIONS* contains a reference for all meson functions and methods. Methods are denoted by [[object_name]].[[method_name]](). *OBJECTS* contains additional information about each object.""",
+ )
+
+ page.section("FUNCTIONS")
+ for f in self.sorted_and_filtered(self.functions):
+ self.generate_function(page, f)
+
+ for obj in self.sorted_and_filtered(self.objects):
+ for f in self.sorted_and_filtered(obj.methods):
+ self.generate_function(page, f, obj)
+
+ page.section("OBJECTS")
+ for obj in self.sorted_and_filtered(self.objects):
+ self.generate_object(page, obj)
+
+ page.section("SEE ALSO")
+ for i in range(len(self.links)):
+ link = self.links[i]
+ page.line(f"[{i + 1}] {link}")
+ page.br()
+
+ page.write()
diff --git a/docs/refman/main.py b/docs/refman/main.py
index 5bc40f7..e2654c9 100644
--- a/docs/refman/main.py
+++ b/docs/refman/main.py
@@ -27,13 +27,14 @@ from .generatorjson import GeneratorJSON
from .generatorprint import GeneratorPrint
from .generatorpickle import GeneratorPickle
from .generatormd import GeneratorMD
+from .generatorman import GeneratorMan
meson_root = Path(__file__).absolute().parents[2]
def main() -> int:
parser = argparse.ArgumentParser(description='Meson reference manual generator')
parser.add_argument('-l', '--loader', type=str, default='yaml', choices=['yaml', 'pickle'], help='Information loader backend')
- parser.add_argument('-g', '--generator', type=str, choices=['print', 'pickle', 'md', 'json'], required=True, help='Generator backend')
+ parser.add_argument('-g', '--generator', type=str, choices=['print', 'pickle', 'md', 'json', 'man'], required=True, help='Generator backend')
parser.add_argument('-s', '--sitemap', type=Path, default=meson_root / 'docs' / 'sitemap.txt', help='Path to the input sitemap.txt')
parser.add_argument('-o', '--out', type=Path, required=True, help='Output directory for generated files')
parser.add_argument('-i', '--input', type=Path, default=meson_root / 'docs' / 'yaml', help='Input path for the selected loader')
@@ -59,6 +60,7 @@ def main() -> int:
'pickle': lambda: GeneratorPickle(refMan, args.out),
'md': lambda: GeneratorMD(refMan, args.out, args.sitemap, args.link_defs, not args.no_modules),
'json': lambda: GeneratorJSON(refMan, args.out, not args.no_modules),
+ 'man': lambda: GeneratorMan(refMan, args.out, not args.no_modules),
}
generator = generators[args.generator]()
diff --git a/docs/sitemap.txt b/docs/sitemap.txt
index 15564d7..82e0a7b 100644
--- a/docs/sitemap.txt
+++ b/docs/sitemap.txt
@@ -53,7 +53,6 @@ index.md
Qt4-module.md
Qt5-module.md
Qt6-module.md
- RPM-module.md
Rust-module.md
Simd-module.md
SourceSet-module.md
@@ -86,8 +85,8 @@ index.md
Using-wraptool.md
Wrap-best-practices-and-tips.md
Shipping-prebuilt-binaries-as-wraps.md
- fallback-wraptool.md
Release-notes.md
+ Release-notes-for-0.61.0.md
Release-notes-for-0.60.0.md
Release-notes-for-0.59.0.md
Release-notes-for-0.58.0.md
diff --git a/docs/theme/extra/templates/navbar_links.html b/docs/theme/extra/templates/navbar_links.html
index b8b6179..c518de5 100644
--- a/docs/theme/extra/templates/navbar_links.html
+++ b/docs/theme/extra/templates/navbar_links.html
@@ -23,7 +23,6 @@
("Qt4-module.html","Qt4"), \
("Qt5-module.html","Qt5"), \
("Qt6-module.html","Qt6"), \
- ("RPM-module.html","RPM"), \
("Rust-module.html","Rust"), \
("Simd-module.html","Simd"), \
("SourceSet-module.html","SourceSet"), \
diff --git a/docs/yaml/builtins/meson.yaml b/docs/yaml/builtins/meson.yaml
index 4f2d24d..00ade2e 100644
--- a/docs/yaml/builtins/meson.yaml
+++ b/docs/yaml/builtins/meson.yaml
@@ -34,18 +34,17 @@ methods:
posargs:
script_name:
- type: str | file | external_program | exe | custom_tgt | custom_idx
+ type: str | file | external_program
description: |
The script to execute.
- *(since 0.55.0)* The output of [[configure_file]], [[files]], and [[find_program]]
- as well as strings are accepted.
+ *(since 0.55.0)* The output of [[find_program]] as well as strings are accepted.
*(since 0.57.0)* [[@file]] objects and the output of [[configure_file]] may be used.
varargs:
name: arg
- type: str | file | external_program | exe | custom_tgt | custom_idx
+ type: str | file | external_program
since: 0.49.0
description: |
Additional arguments
@@ -53,8 +52,6 @@ methods:
*(since 0.55.0)* The output of [[configure_file]], [[files]], and [[find_program]]
as well as strings are accepted.
- *(since 0.57.0)* [[@file]] objects and the output of [[configure_file]] may be used.
-
- name: add_install_script
returns: void
description: |
@@ -89,8 +86,26 @@ methods:
shell would. If your script uses Python, `shlex.split()` is the
easiest correct way to do this.
- posargs_inherit: meson.add_dist_script
- varargs_inherit: meson.add_dist_script
+ posargs:
+ script_name:
+ type: str | file | external_program | exe | custom_tgt | custom_idx
+ description: |
+ The script to execute.
+
+ *(since 0.55.0)* The output of [[find_program]], [[executable]],
+ [[custom_target]], as well as strings are accepted.
+
+ *(since 0.57.0)* [[@file]] objects and the output of [[configure_file]] may be used.
+
+ varargs:
+ name: arg
+ type: str | file | external_program | exe | custom_tgt | custom_idx
+ since: 0.49.0
+ description: |
+ Additional arguments
+
+ *(since 0.55.0)* The output of [[find_program]], [[executable]],
+ [[custom_target]], as well as strings are accepted.
kwargs:
skip_if_destdir:
diff --git a/docs/yaml/objects/cfg_data.yaml b/docs/yaml/objects/cfg_data.yaml
index 9a66b73..5cc4b84 100644
--- a/docs/yaml/objects/cfg_data.yaml
+++ b/docs/yaml/objects/cfg_data.yaml
@@ -41,8 +41,17 @@ methods:
type: str
description: The name of the variable to set
value:
- type: bool
- description: The value to set as either `1` or `0`
+ type: bool | int
+ description: |
+ The value to set as either `1` or `0`
+
+ Passing numbers was never intended to work, and since 0.62 it has been
+ deprecated. It will be removed in a future version of Meson. If you
+ need to pass numbers use the `.set` method.
+ warnings:
+ - numeric values < 0 have the surprising behavior of being converted to
+ [[true]], values > 1 have the more expected but unintentional behavior of
+ being interpretered as [[true]].
kwargs_inherit: cfg_data.set
diff --git a/docs/yaml/objects/dep.yaml b/docs/yaml/objects/dep.yaml
index 23092c2..d847690 100644
--- a/docs/yaml/objects/dep.yaml
+++ b/docs/yaml/objects/dep.yaml
@@ -205,7 +205,7 @@ methods:
default_value:
type: str
- description: The davault value to return when the variable does not exist
+ description: The default value to return when the variable does not exist
pkgconfig_define:
type: list[str]
diff --git a/docs/yaml/objects/feature.yaml b/docs/yaml/objects/feature.yaml
index 5b451e5..b6a754b 100644
--- a/docs/yaml/objects/feature.yaml
+++ b/docs/yaml/objects/feature.yaml
@@ -54,7 +54,7 @@ methods:
if get_option('directx').require(host_machine.system() == 'windows',
error_message: 'DirectX only available on Windows').allowed() then
src += ['directx.c']
- config.set10('HAVE_DIRECTX', 1)
+ config.set10('HAVE_DIRECTX', true)
endif
```
diff --git a/man/meson.1 b/man/meson.1
index b6fbf69..0443d6e 100644
--- a/man/meson.1
+++ b/man/meson.1
@@ -1,4 +1,4 @@
-.TH MESON "1" "October 2021" "meson 0.60.0" "User Commands"
+.TH MESON "1" "January 2022" "meson 0.61.0" "User Commands"
.SH NAME
meson - a high productivity build system
.SH DESCRIPTION
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 4b368e7..e43c8c7 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -13,6 +13,7 @@
# limitations under the License.
from collections import OrderedDict
+from dataclasses import dataclass, InitVar
from functools import lru_cache
from itertools import chain
from pathlib import Path
@@ -61,11 +62,11 @@ if T.TYPE_CHECKING:
# Assembly files cannot be unitified and neither can LLVM IR files
LANGS_CANT_UNITY = ('d', 'fortran', 'vala')
+@dataclass(eq=False)
class RegenInfo:
- def __init__(self, source_dir: str, build_dir: str, depfiles: T.List[str]):
- self.source_dir = source_dir
- self.build_dir = build_dir
- self.depfiles = depfiles
+ source_dir: str
+ build_dir: str
+ depfiles: T.List[str]
class TestProtocol(enum.Enum):
@@ -97,28 +98,30 @@ class TestProtocol(enum.Enum):
return 'tap'
+@dataclass(eq=False)
class CleanTrees:
'''
Directories outputted by custom targets that have to be manually cleaned
because on Linux `ninja clean` only deletes empty directories.
'''
- def __init__(self, build_dir: str, trees: T.List[str]):
- self.build_dir = build_dir
- self.trees = trees
+ build_dir: str
+ trees: T.List[str]
+@dataclass(eq=False)
class InstallData:
- def __init__(self, source_dir: str, build_dir: str, prefix: str, libdir: str,
- strip_bin: T.List[str], install_umask: T.Union[str, int],
- mesonintrospect: T.List[str], version: str,
- is_cross_build: bool):
- # TODO: in python 3.8 or with typing_Extensions install_umask could be:
- # `T.Union[T.Literal['preserve'], int]`, which would be more accurate.
- self.source_dir = source_dir
- self.build_dir = build_dir
- self.prefix = prefix
- self.libdir = libdir
- self.strip_bin = strip_bin
- self.install_umask = install_umask
+ source_dir: str
+ build_dir: str
+ prefix: str
+ libdir: str
+ strip_bin: T.List[str]
+ # TODO: in python 3.8 or with typing_Extensions this could be:
+ # `T.Union[T.Literal['preserve'], int]`, which would be more accurate.
+ install_umask: T.Union[str, int]
+ mesonintrospect: T.List[str]
+ version: str
+ is_cross_build: bool
+
+ def __post_init__(self) -> None:
self.targets: T.List[TargetInstallData] = []
self.headers: T.List[InstallDataBase] = []
self.man: T.List[InstallDataBase] = []
@@ -127,59 +130,52 @@ class InstallData:
self.symlinks: T.List[InstallSymlinkData] = []
self.install_scripts: T.List[ExecutableSerialisation] = []
self.install_subdirs: T.List[SubdirInstallData] = []
- self.mesonintrospect = mesonintrospect
- self.version = version
- self.is_cross_build = is_cross_build
+@dataclass(eq=False)
class TargetInstallData:
-
+ fname: str
+ outdir: str
+ outdir_name: InitVar[str]
+ aliases: T.Dict[str, str]
+ strip: bool
+ install_name_mappings: T.Mapping[str, str]
+ rpath_dirs_to_remove: T.Set[bytes]
+ install_rpath: str
# TODO: install_mode should just always be a FileMode object
+ install_mode: T.Optional['FileMode']
+ subproject: str
+ optional: bool = False
+ tag: T.Optional[str] = None
- def __init__(self, fname: str, outdir: str, outdir_name: str, aliases: T.Dict[str, str],
- strip: bool, install_name_mappings: T.Mapping[str, str], rpath_dirs_to_remove: T.Set[bytes],
- install_rpath: str, install_mode: T.Optional['FileMode'],
- subproject: str, optional: bool = False, tag: T.Optional[str] = None):
- self.fname = fname
- self.outdir = outdir
- self.out_name = os.path.join(outdir_name, os.path.basename(fname))
- self.aliases = aliases
- self.strip = strip
- self.install_name_mappings = install_name_mappings
- self.rpath_dirs_to_remove = rpath_dirs_to_remove
- self.install_rpath = install_rpath
- self.install_mode = install_mode
- self.subproject = subproject
- self.optional = optional
- self.tag = tag
+ def __post_init__(self, outdir_name: str) -> None:
+ self.out_name = os.path.join(outdir_name, os.path.basename(self.fname))
+@dataclass(eq=False)
class InstallEmptyDir:
- def __init__(self, path: str, install_mode: 'FileMode', subproject: str, tag: T.Optional[str] = None):
- self.path = path
- self.install_mode = install_mode
- self.subproject = subproject
- self.tag = tag
+ path: str
+ install_mode: 'FileMode'
+ subproject: str
+ tag: T.Optional[str] = None
+@dataclass(eq=False)
class InstallDataBase:
- def __init__(self, path: str, install_path: str, install_path_name: str,
- install_mode: 'FileMode', subproject: str, tag: T.Optional[str] = None,
- data_type: T.Optional[str] = None):
- self.path = path
- self.install_path = install_path
- self.install_path_name = install_path_name
- self.install_mode = install_mode
- self.subproject = subproject
- self.tag = tag
- self.data_type = data_type
-
+ path: str
+ install_path: str
+ install_path_name: str
+ install_mode: 'FileMode'
+ subproject: str
+ tag: T.Optional[str] = None
+ data_type: T.Optional[str] = None
+
+@dataclass(eq=False)
class InstallSymlinkData:
- def __init__(self, target: str, name: str, install_path: str,
- subproject: str, tag: T.Optional[str] = None):
- self.target = target
- self.name = name
- self.install_path = install_path
- self.subproject = subproject
- self.tag = tag
+ target: str
+ name: str
+ install_path: str
+ subproject: str
+ tag: T.Optional[str] = None
+# cannot use dataclass here because "exclude" is out of order
class SubdirInstallData(InstallDataBase):
def __init__(self, path: str, install_path: str, install_path_name: str,
install_mode: 'FileMode', exclude: T.Tuple[T.Set[str], T.Set[str]],
@@ -187,64 +183,53 @@ class SubdirInstallData(InstallDataBase):
super().__init__(path, install_path, install_path_name, install_mode, subproject, tag, data_type)
self.exclude = exclude
+@dataclass(eq=False)
class ExecutableSerialisation:
# XXX: should capture and feed default to False, instead of None?
- def __init__(self, cmd_args: T.List[str],
- env: T.Optional[build.EnvironmentVariables] = None,
- exe_wrapper: T.Optional['programs.ExternalProgram'] = None,
- workdir: T.Optional[str] = None,
- extra_paths: T.Optional[T.List] = None,
- capture: T.Optional[bool] = None,
- feed: T.Optional[bool] = None,
- tag: T.Optional[str] = None,
- verbose: bool = False,
- ) -> None:
- self.cmd_args = cmd_args
- self.env = env
- if exe_wrapper is not None:
- assert isinstance(exe_wrapper, programs.ExternalProgram)
- self.exe_wrapper = exe_wrapper
- self.workdir = workdir
- self.extra_paths = extra_paths
- self.capture = capture
- self.feed = feed
+ cmd_args: T.List[str]
+ env: T.Optional[build.EnvironmentVariables] = None
+ exe_wrapper: T.Optional['programs.ExternalProgram'] = None
+ workdir: T.Optional[str] = None
+ extra_paths: T.Optional[T.List] = None
+ capture: T.Optional[bool] = None
+ feed: T.Optional[bool] = None
+ tag: T.Optional[str] = None
+ verbose: bool = False
+
+ def __post_init__(self) -> None:
+ if self.exe_wrapper is not None:
+ assert isinstance(self.exe_wrapper, programs.ExternalProgram)
self.pickled = False
self.skip_if_destdir = False
- self.verbose = verbose
self.subproject = ''
- self.tag = tag
+@dataclass(eq=False)
class TestSerialisation:
- def __init__(self, name: str, project: str, suite: T.List[str], fname: T.List[str],
- is_cross_built: bool, exe_wrapper: T.Optional[programs.ExternalProgram],
- needs_exe_wrapper: bool, is_parallel: bool, cmd_args: T.List[str],
- env: build.EnvironmentVariables, should_fail: bool,
- timeout: T.Optional[int], workdir: T.Optional[str],
- extra_paths: T.List[str], protocol: TestProtocol, priority: int,
- cmd_is_built: bool, depends: T.List[str], version: str):
- self.name = name
- self.project_name = project
- self.suite = suite
- self.fname = fname
- self.is_cross_built = is_cross_built
- if exe_wrapper is not None:
- assert isinstance(exe_wrapper, programs.ExternalProgram)
- self.exe_wrapper = exe_wrapper
- self.is_parallel = is_parallel
- self.cmd_args = cmd_args
- self.env = env
- self.should_fail = should_fail
- self.timeout = timeout
- self.workdir = workdir
- self.extra_paths = extra_paths
- self.protocol = protocol
- self.priority = priority
- self.needs_exe_wrapper = needs_exe_wrapper
- self.cmd_is_built = cmd_is_built
- self.depends = depends
- self.version = version
+ name: str
+ project_name: str
+ suite: T.List[str]
+ fname: T.List[str]
+ is_cross_built: bool
+ exe_wrapper: T.Optional[programs.ExternalProgram]
+ needs_exe_wrapper: bool
+ is_parallel: bool
+ cmd_args: T.List[str]
+ env: build.EnvironmentVariables
+ should_fail: bool
+ timeout: T.Optional[int]
+ workdir: T.Optional[str]
+ extra_paths: T.List[str]
+ protocol: TestProtocol
+ priority: int
+ cmd_is_built: bool
+ depends: T.List[str]
+ version: str
+
+ def __post_init__(self) -> None:
+ if self.exe_wrapper is not None:
+ assert isinstance(self.exe_wrapper, programs.ExternalProgram)
def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, interpreter: T.Optional['Interpreter'] = None) -> T.Optional['Backend']:
@@ -708,7 +693,6 @@ class Backend:
return False
def get_external_rpath_dirs(self, target: build.BuildTarget) -> T.Set[str]:
- dirs: T.Set[str] = set()
args: T.List[str] = []
for lang in LANGUAGES_USING_LDFLAGS:
try:
@@ -719,6 +703,11 @@ class Backend:
args.extend(e)
except Exception:
pass
+ return self.get_rpath_dirs_from_link_args(args)
+
+ @staticmethod
+ def get_rpath_dirs_from_link_args(args: T.List[str]) -> T.Set[str]:
+ dirs: T.Set[str] = set()
# Match rpath formats:
# -Wl,-rpath=
# -Wl,-rpath,
@@ -751,37 +740,38 @@ class Backend:
return dirs
@lru_cache(maxsize=None)
- def rpaths_for_bundled_shared_libraries(self, target: build.BuildTarget, exclude_system: bool = True) -> 'ImmutableListProtocol[str]':
- paths: T.List[str] = []
+ def rpaths_for_non_system_absolute_shared_libraries(self, target: build.BuildTarget, exclude_system: bool = True) -> 'ImmutableListProtocol[str]':
+ paths: OrderedSet[str] = OrderedSet()
for dep in target.external_deps:
if not isinstance(dep, (dependencies.ExternalLibrary, dependencies.PkgConfigDependency)):
continue
- la = dep.link_args
- if len(la) != 1 or not os.path.isabs(la[0]):
- continue
- # The only link argument is an absolute path to a library file.
- libpath = la[0]
- libdir = os.path.dirname(libpath)
- if exclude_system and self._libdir_is_system(libdir, target.compilers, self.environment):
- # No point in adding system paths.
- continue
- # Don't remove rpaths specified in LDFLAGS.
- if libdir in self.get_external_rpath_dirs(target):
- continue
- # Windows doesn't support rpaths, but we use this function to
- # emulate rpaths by setting PATH, so also accept DLLs here
- if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so', '.dylib']:
- continue
- if libdir.startswith(self.environment.get_source_dir()):
- rel_to_src = libdir[len(self.environment.get_source_dir()) + 1:]
- assert not os.path.isabs(rel_to_src), f'rel_to_src: {rel_to_src} is absolute'
- paths.append(os.path.join(self.build_to_src, rel_to_src))
- else:
- paths.append(libdir)
+ for libpath in dep.link_args:
+ # For all link args that are absolute paths to a library file, add RPATH args
+ if not os.path.isabs(libpath):
+ continue
+ libdir = os.path.dirname(libpath)
+ if exclude_system and self._libdir_is_system(libdir, target.compilers, self.environment):
+ # No point in adding system paths.
+ continue
+ # Don't remove rpaths specified in LDFLAGS.
+ if libdir in self.get_external_rpath_dirs(target):
+ continue
+ # Windows doesn't support rpaths, but we use this function to
+ # emulate rpaths by setting PATH, so also accept DLLs here
+ if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so', '.dylib']:
+ continue
+ if libdir.startswith(self.environment.get_source_dir()):
+ rel_to_src = libdir[len(self.environment.get_source_dir()) + 1:]
+ assert not os.path.isabs(rel_to_src), f'rel_to_src: {rel_to_src} is absolute'
+ paths.add(os.path.join(self.build_to_src, rel_to_src))
+ else:
+ paths.add(libdir)
+ # Don't remove rpaths specified by the dependency
+ paths.difference_update(self.get_rpath_dirs_from_link_args(dep.link_args))
for i in chain(target.link_targets, target.link_whole_targets):
if isinstance(i, build.BuildTarget):
- paths.extend(self.rpaths_for_bundled_shared_libraries(i, exclude_system))
- return paths
+ paths.update(self.rpaths_for_non_system_absolute_shared_libraries(i, exclude_system))
+ return list(paths)
# This may take other types
def determine_rpath_dirs(self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]
@@ -794,7 +784,7 @@ class Backend:
result = OrderedSet()
result.add('meson-out')
if isinstance(target, build.BuildTarget):
- result.update(self.rpaths_for_bundled_shared_libraries(target))
+ result.update(self.rpaths_for_non_system_absolute_shared_libraries(target))
target.rpath_dirs_to_remove.update([d.encode('utf-8') for d in result])
return tuple(result)
@@ -1068,11 +1058,11 @@ class Backend:
tests.
"""
result: T.Set[str] = set()
- prospectives: T.Set[build.Target] = set()
+ prospectives: T.Set[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]] = set()
if isinstance(target, build.BuildTarget):
prospectives.update(target.get_transitive_link_deps())
# External deps
- for deppath in self.rpaths_for_bundled_shared_libraries(target, exclude_system=False):
+ for deppath in self.rpaths_for_non_system_absolute_shared_libraries(target, exclude_system=False):
result.add(os.path.normpath(os.path.join(self.environment.get_build_dir(), deppath)))
for bdep in extra_bdeps:
prospectives.add(bdep)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index b6621c9..ed1fe8c 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1004,7 +1004,8 @@ class NinjaBackend(backends.Backend):
extra_bdeps=target.get_transitive_build_target_deps(),
capture=ofilenames[0] if target.capture else None,
feed=srcs[0] if target.feed else None,
- env=target.env)
+ env=target.env,
+ verbose=target.console)
if reason:
cmd_type = f' (wrapped by meson {reason})'
else:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 7c873b2..a392f98 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -13,6 +13,7 @@
# limitations under the License.
from collections import OrderedDict
+from dataclasses import dataclass, field
from functools import lru_cache
import copy
import hashlib
@@ -130,22 +131,19 @@ def get_target_macos_dylib_install_name(ld) -> str:
class InvalidArguments(MesonException):
pass
+@dataclass(eq=False)
class DependencyOverride(HoldableObject):
- def __init__(self, dep: dependencies.Dependency, node: 'BaseNode', explicit: bool = True):
- self.dep = dep
- self.node = node
- self.explicit = explicit
+ dep: dependencies.Dependency
+ node: 'BaseNode'
+ explicit: bool = True
+@dataclass(eq=False)
class Headers(HoldableObject):
-
- def __init__(self, sources: T.List[File], install_subdir: T.Optional[str],
- custom_install_dir: T.Optional[str], custom_install_mode: 'FileMode',
- subproject: str):
- self.sources = sources
- self.install_subdir = install_subdir
- self.custom_install_dir = custom_install_dir
- self.custom_install_mode = custom_install_mode
- self.subproject = subproject
+ sources: T.List[File]
+ install_subdir: T.Optional[str]
+ custom_install_dir: T.Optional[str]
+ custom_install_mode: 'FileMode'
+ subproject: str
# TODO: we really don't need any of these methods, but they're preserved to
# keep APIs relying on them working.
@@ -166,16 +164,13 @@ class Headers(HoldableObject):
return self.custom_install_mode
+@dataclass(eq=False)
class Man(HoldableObject):
-
- def __init__(self, sources: T.List[File], custom_install_dir: T.Optional[str],
- custom_install_mode: 'FileMode', subproject: str,
- locale: T.Optional[str]):
- self.sources = sources
- self.custom_install_dir = custom_install_dir
- self.custom_install_mode = custom_install_mode
- self.subproject = subproject
- self.locale = locale
+ sources: T.List[File]
+ custom_install_dir: T.Optional[str]
+ custom_install_mode: 'FileMode'
+ subproject: str
+ locale: T.Optional[str]
def get_custom_install_dir(self) -> T.Optional[str]:
return self.custom_install_dir
@@ -187,40 +182,30 @@ class Man(HoldableObject):
return self.sources
+@dataclass(eq=False)
class EmptyDir(HoldableObject):
-
- def __init__(self, path: str, install_mode: 'FileMode', subproject: str,
- install_tag: T.Optional[str] = None):
- self.path = path
- self.install_mode = install_mode
- self.subproject = subproject
- self.install_tag = install_tag
+ path: str
+ install_mode: 'FileMode'
+ subproject: str
+ install_tag: T.Optional[str] = None
+@dataclass(eq=False)
class InstallDir(HoldableObject):
+ source_subdir: str
+ installable_subdir: str
+ install_dir: str
+ install_mode: 'FileMode'
+ exclude: T.Tuple[T.Set[str], T.Set[str]]
+ strip_directory: bool
+ subproject: str
+ from_source_dir: bool = True
+ install_tag: T.Optional[str] = None
- def __init__(self, source_subdir: str, installable_subdir: str, install_dir: str,
- install_mode: 'FileMode',
- exclude: T.Tuple[T.Set[str], T.Set[str]],
- strip_directory: bool, subproject: str,
- from_source_dir: bool = True,
- install_tag: T.Optional[str] = None):
- self.source_subdir = source_subdir
- self.installable_subdir = installable_subdir
- self.install_dir = install_dir
- self.install_mode = install_mode
- self.exclude = exclude
- self.strip_directory = strip_directory
- self.from_source_dir = from_source_dir
- self.subproject = subproject
- self.install_tag = install_tag
-
-
+@dataclass(eq=False)
class DepManifest:
-
- def __init__(self, version: str, license: T.List[str]):
- self.version = version
- self.license = license
+ version: str
+ license: T.List[str]
def to_json(self) -> T.Dict[str, T.Union[str, T.List[str]]]:
return {
@@ -229,6 +214,7 @@ class DepManifest:
}
+# literally everything isn't dataclass stuff
class Build:
"""A class that holds the status of one build including
all dependencies and so on.
@@ -363,18 +349,17 @@ class Build:
return link_args.get(compiler.get_language(), [])
+@dataclass(eq=False)
class IncludeDirs(HoldableObject):
"""Internal representation of an include_directories call."""
- def __init__(self, curdir: str, incdirs: T.List[str], is_system: bool, extra_build_dirs: T.Optional[T.List[str]] = None):
- self.curdir = curdir
- self.incdirs = incdirs
- self.is_system = is_system
-
- # Interpreter has validated that all given directories
- # actually exist.
- self.extra_build_dirs: T.List[str] = extra_build_dirs or []
+ curdir: str
+ incdirs: T.List[str]
+ is_system: bool
+ # Interpreter has validated that all given directories
+ # actually exist.
+ extra_build_dirs: T.List[str] = field(default_factory=list)
def __repr__(self) -> str:
r = '<{} {}/{}>'
@@ -404,21 +389,18 @@ class IncludeDirs(HoldableObject):
strlist.append(os.path.join(builddir, self.curdir, idir))
return strlist
+@dataclass(eq=False)
class ExtractedObjects(HoldableObject):
'''
Holds a list of sources for which the objects must be extracted
'''
- def __init__(self, target: 'BuildTarget',
- srclist: T.Optional[T.List[File]] = None,
- genlist: T.Optional[T.List['GeneratedTypes']] = None,
- objlist: T.Optional[T.List[T.Union[str, 'File', 'ExtractedObjects']]] = None,
- recursive: bool = True):
- self.target = target
- self.recursive = recursive
- self.srclist: T.List[File] = srclist if srclist is not None else []
- self.genlist: T.List['GeneratedTypes'] = genlist if genlist is not None else []
- self.objlist: T.Optional[T.List[T.Union[str, 'File', 'ExtractedObjects']]] = \
- objlist if objlist is not None else []
+ target: 'BuildTarget'
+ srclist: T.List[File] = field(default_factory=list)
+ genlist: T.List['GeneratedTypes'] = field(default_factory=list)
+ objlist: T.List[T.Union[str, 'File', 'ExtractedObjects']] = field(default_factory=list)
+ recursive: bool = True
+
+ def __post_init__(self) -> None:
if self.target.is_unity:
self.check_unity_compatible()
@@ -523,23 +505,25 @@ class EnvironmentVariables(HoldableObject):
env[name] = method(env, name, values, separator)
return env
+@dataclass(eq=False)
class Target(HoldableObject):
# TODO: should Target be an abc.ABCMeta?
- def __init__(self, name: str, subdir: str, subproject: str, build_by_default: bool, for_machine: MachineChoice):
- if has_path_sep(name):
+ name: str
+ subdir: str
+ subproject: str
+ build_by_default: bool
+ for_machine: MachineChoice
+
+ def __post_init__(self) -> None:
+ if has_path_sep(self.name):
# Fix failing test 53 when this becomes an error.
mlog.warning(textwrap.dedent(f'''\
- Target "{name}" has a path separator in its name.
+ Target "{self.name}" has a path separator in its name.
This is not supported, it can cause unexpected failures and will become
a hard error in the future.\
'''))
- self.name = name
- self.subdir = subdir
- self.subproject = subproject
- self.build_by_default = build_by_default
- self.for_machine = for_machine
self.install = False
self.build_always_stale = False
self.option_overrides_base: T.Dict[OptionKey, str] = {}
@@ -548,6 +532,7 @@ class Target(HoldableObject):
if not hasattr(self, 'typename'):
raise RuntimeError(f'Target type is not set for target class "{type(self).__name__}". This is a bug')
+ # dataclass comparators?
def __lt__(self, other: object) -> bool:
if not isinstance(other, Target):
return NotImplemented
@@ -1016,11 +1001,11 @@ class BuildTarget(Target):
return ExtractedObjects(self, self.sources, self.generated, self.objects,
recursive)
- def get_all_link_deps(self) -> 'ImmutableListProtocol[Target]':
+ def get_all_link_deps(self) -> 'ImmutableListProtocol[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]]':
return self.get_transitive_link_deps()
@lru_cache(maxsize=None)
- def get_transitive_link_deps(self) -> 'ImmutableListProtocol[Target]':
+ def get_transitive_link_deps(self) -> 'ImmutableListProtocol[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]]':
result: T.List[Target] = []
for i in self.link_targets:
result += i.get_all_link_deps()
@@ -1619,6 +1604,7 @@ class Generator(HoldableObject):
def __init__(self, exe: T.Union['Executable', programs.ExternalProgram],
arguments: T.List[str],
output: T.List[str],
+ # how2dataclass
*,
depfile: T.Optional[str] = None,
capture: bool = False,
@@ -1691,24 +1677,27 @@ class Generator(HoldableObject):
return output
+@dataclass(eq=False)
class GeneratedList(HoldableObject):
"""The output of generator.process."""
- def __init__(self, generator: Generator, subdir: str,
- preserve_path_from: T.Optional[str],
- extra_args: T.List[str]):
- self.generator = generator
- self.name = generator.exe
+ generator: Generator
+ subdir: str
+ preserve_path_from: T.Optional[str]
+ extra_args: T.List[str]
+
+ def __post_init__(self) -> None:
+ self.name = self.generator.exe
self.depends: T.Set['CustomTarget'] = set() # Things this target depends on (because e.g. a custom target was used as input)
- self.subdir = subdir
self.infilelist: T.List['File'] = []
self.outfilelist: T.List[str] = []
self.outmap: T.Dict[File, T.List[str]] = {}
self.extra_depends = [] # XXX: Doesn't seem to be used?
self.depend_files: T.List[File] = []
- self.preserve_path_from = preserve_path_from
- self.extra_args: T.List[str] = extra_args if extra_args is not None else []
+
+ if self.extra_args is None:
+ self.extra_args: T.List[str] = []
if isinstance(self.generator.exe, programs.ExternalProgram):
if not self.generator.exe.found():
@@ -1777,8 +1766,8 @@ class Executable(BuildTarget):
self.suffix = 'exe'
elif machine.system.startswith('wasm') or machine.system == 'emscripten':
self.suffix = 'js'
- elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('arm') or
- 'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('arm')):
+ elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('armclang') or
+ 'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('armclang')):
self.suffix = 'axf'
elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('ccrx') or
'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('ccrx')):
@@ -2588,13 +2577,12 @@ class CustomTarget(Target, CommandBase):
return []
def is_internal(self) -> bool:
- if not self.should_install():
- return True
- for out in self.get_outputs():
- # Can't check if this is a static library, so try to guess
- if not out.endswith(('.a', '.lib')):
- return False
- return True
+ '''
+ Returns True iif this is a not installed static library.
+ '''
+ if len(self.outputs) != 1:
+ return False
+ return CustomTargetIndex(self, self.outputs[0]).is_internal()
def extract_all_objects_recurse(self) -> T.List[T.Union[str, 'ExtractedObjects']]:
return self.get_outputs()
@@ -2622,7 +2610,7 @@ class RunTarget(Target, CommandBase):
def __init__(self, name: str,
command: T.Sequence[T.Union[str, File, BuildTarget, 'CustomTarget', 'CustomTargetIndex', programs.ExternalProgram]],
- dependencies: T.Sequence[T.Union[BuildTarget, 'CustomTarget']],
+ dependencies: T.Sequence[Target],
subdir: str,
subproject: str,
env: T.Optional['EnvironmentVariables'] = None):
@@ -2666,7 +2654,7 @@ class RunTarget(Target, CommandBase):
return "@run"
class AliasTarget(RunTarget):
- def __init__(self, name: str, dependencies: T.Sequence[T.Union[BuildTarget, 'CustomTarget']],
+ def __init__(self, name: str, dependencies: T.Sequence['Target'],
subdir: str, subproject: str):
super().__init__(name, [], dependencies, subdir, subproject)
@@ -2713,6 +2701,7 @@ class Jar(BuildTarget):
return ['-cp', os.pathsep.join(cp_paths)]
return []
+@dataclass(eq=False)
class CustomTargetIndex(HoldableObject):
"""A special opaque object returned by indexing a CustomTarget. This object
@@ -2721,11 +2710,12 @@ class CustomTargetIndex(HoldableObject):
the sources.
"""
- def __init__(self, target: CustomTarget, output: str):
+ target: CustomTarget
+ output: str
+
+ def __post_init__(self) -> None:
self.typename = 'custom'
- self.target = target
- self.output = output
- self.for_machine = target.for_machine
+ self.for_machine = self.target.for_machine
@property
def name(self) -> str:
@@ -2764,7 +2754,11 @@ class CustomTargetIndex(HoldableObject):
return self.target.should_install()
def is_internal(self) -> bool:
- return self.target.is_internal()
+ '''
+ Returns True iif this is a not installed static library
+ '''
+ suf = os.path.splitext(self.output)[-1]
+ return suf in {'.a', '.lib'} and not self.should_install()
def extract_all_objects_recurse(self) -> T.List[T.Union[str, 'ExtractedObjects']]:
return self.target.extract_all_objects_recurse()
@@ -2773,17 +2767,16 @@ class CustomTargetIndex(HoldableObject):
return self.target.get_custom_install_dir()
class ConfigurationData(HoldableObject):
- def __init__(self) -> None:
+ def __init__(self, initial_values: T.Optional[T.Union[
+ T.Dict[str, T.Tuple[T.Union[str, int, bool], T.Optional[str]]],
+ T.Dict[str, T.Union[str, int, bool]]]
+ ] = None):
super().__init__()
- self.values: T.Dict[
- str,
- T.Tuple[
- T.Union[str, int, bool],
- T.Optional[str]
- ]
- ] = {}
+ self.values: T.Dict[str, T.Tuple[T.Union[str, int, bool], T.Optional[str]]] = \
+ {k: v if isinstance(v, tuple) else (v, None) for k, v in initial_values.items()} if initial_values else {}
+ self.used: bool = False
- def __repr__(self):
+ def __repr__(self) -> str:
return repr(self.values)
def __contains__(self, value: str) -> bool:
@@ -2797,45 +2790,41 @@ class ConfigurationData(HoldableObject):
# A bit poorly named, but this represents plain data files to copy
# during install.
+@dataclass(eq=False)
class Data(HoldableObject):
- def __init__(self, sources: T.List[File], install_dir: str, install_dir_name: str,
- install_mode: 'FileMode', subproject: str,
- rename: T.List[str] = None,
- install_tag: T.Optional[str] = None,
- data_type: str = None):
- self.sources = sources
- self.install_dir = install_dir
- self.install_dir_name = install_dir_name
- self.install_mode = install_mode
- self.install_tag = install_tag
- if rename is None:
+ sources: T.List[File]
+ install_dir: str
+ install_dir_name: str
+ install_mode: 'FileMode'
+ subproject: str
+ rename: T.List[str] = None
+ install_tag: T.Optional[str] = None
+ data_type: str = None
+
+ def __post_init__(self) -> None:
+ if self.rename is None:
self.rename = [os.path.basename(f.fname) for f in self.sources]
- else:
- self.rename = rename
- self.subproject = subproject
- self.data_type = data_type
+@dataclass(eq=False)
class SymlinkData(HoldableObject):
- def __init__(self, target: str, name: str, install_dir: str,
- subproject: str, install_tag: T.Optional[str] = None):
- self.target = target
- if name != os.path.basename(name):
- raise InvalidArguments(f'Link name is "{name}", but link names cannot contain path separators. '
+ target: str
+ name: str
+ install_dir: str
+ subproject: str
+ install_tag: T.Optional[str] = None
+
+ def __post_init__(self) -> None:
+ if self.name != os.path.basename(self.name):
+ raise InvalidArguments(f'Link name is "{self.name}", but link names cannot contain path separators. '
'The dir part should be in install_dir.')
- self.name = name
- self.install_dir = install_dir
- self.subproject = subproject
- self.install_tag = install_tag
+@dataclass(eq=False)
class TestSetup:
- def __init__(self, exe_wrapper: T.List[str], gdb: bool,
- timeout_multiplier: int, env: EnvironmentVariables,
- exclude_suites: T.List[str]):
- self.exe_wrapper = exe_wrapper
- self.gdb = gdb
- self.timeout_multiplier = timeout_multiplier
- self.env = env
- self.exclude_suites = exclude_suites
+ exe_wrapper: T.List[str]
+ gdb: bool
+ timeout_multiplier: int
+ env: EnvironmentVariables
+ exclude_suites: T.List[str]
def get_sources_string_names(sources, backend):
'''
diff --git a/test cases/unit/98 install all targets/bar-custom.txt b/mesonbuild/cmake/data/__init__.py
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/bar-custom.txt
+++ b/mesonbuild/cmake/data/__init__.py
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index c2e2d27..0b6d241 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -24,7 +24,7 @@ from .traceparser import CMakeTraceParser, CMakeGeneratorTarget
from .tracetargets import resolve_cmake_trace_targets
from .. import mlog, mesonlib
from ..mesonlib import MachineChoice, OrderedSet, version_compare, path_is_in_root, relative_to_if_possible, OptionKey
-from ..mesondata import mesondata
+from ..mesondata import DataFile
from ..compilers.compilers import assembler_suffixes, lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header
from ..programs import ExternalProgram
from ..coredata import FORBIDDEN_TARGET_NAMES
@@ -816,7 +816,7 @@ class CMakeInterpreter:
raise CMakeException('Unable to find CMake')
self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, permissive=True)
- preload_file = mesondata['cmake/data/preload.cmake'].write_to_private(self.env)
+ preload_file = DataFile('cmake/data/preload.cmake').write_to_private(self.env)
toolchain = CMakeToolchain(cmake_exe, self.env, self.for_machine, CMakeExecScope.SUBPROJECT, self.build_dir, preload_file)
toolchain_file = toolchain.write()
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 9d4a779..474bf3b 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -183,6 +183,11 @@ class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler):
return []
+class ArmLtdClangCCompiler(ClangCCompiler):
+
+ id = 'armltdclang'
+
+
class AppleClangCCompiler(ClangCCompiler):
"""Handle the differences between Apple Clang and Vanilla Clang.
@@ -197,6 +202,9 @@ class AppleClangCCompiler(ClangCCompiler):
class EmscriptenCCompiler(EmscriptenMixin, ClangCCompiler):
+
+ id = 'emscripten'
+
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,
@@ -207,10 +215,13 @@ class EmscriptenCCompiler(EmscriptenMixin, ClangCCompiler):
ClangCCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper=exe_wrapper, linker=linker,
defines=defines, full_version=full_version)
- self.id = 'emscripten'
class ArmclangCCompiler(ArmclangCompiler, CCompiler):
+ '''
+ Keil armclang
+ '''
+
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,
@@ -315,6 +326,9 @@ class PGICCompiler(PGICompiler, CCompiler):
class NvidiaHPC_CCompiler(PGICompiler, CCompiler):
+
+ id = 'nvidia_hpc'
+
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,
@@ -322,7 +336,6 @@ class NvidiaHPC_CCompiler(PGICompiler, CCompiler):
CCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, linker=linker, full_version=full_version)
PGICompiler.__init__(self)
- self.id = 'nvidia_hpc'
class ElbrusCCompiler(ElbrusCompiler, CCompiler):
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index e0745c2..b652f5a 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -875,7 +875,7 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
return None
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 8bc013f..749da2f 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -155,7 +155,7 @@ class CPPCompiler(CLikeCompiler, Compiler):
}
# Currently, remapping is only supported for Clang, Elbrus and GCC
- assert self.id in frozenset(['clang', 'lcc', 'gcc', 'emscripten'])
+ assert self.id in frozenset(['clang', 'lcc', 'gcc', 'emscripten', 'armltdclang'])
if cpp_std not in CPP_FALLBACKS:
# 'c++03' and 'c++98' don't have fallback types
@@ -259,6 +259,11 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
return search_dirs + ['-lstdc++']
+class ArmLtdClangCPPCompiler(ClangCPPCompiler):
+
+ id = 'armltdclang'
+
+
class AppleClangCPPCompiler(ClangCPPCompiler):
def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]:
# We need to apply the search prefix here, as these link arguments may
@@ -274,6 +279,9 @@ class AppleClangCPPCompiler(ClangCPPCompiler):
class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
+
+ id = 'emscripten'
+
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,
@@ -284,7 +292,6 @@ class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
ClangCPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper=exe_wrapper, linker=linker,
defines=defines, full_version=full_version)
- self.id = 'emscripten'
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
@@ -296,6 +303,10 @@ class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
+ '''
+ Keil armclang
+ '''
+
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,
@@ -438,6 +449,9 @@ class PGICPPCompiler(PGICompiler, CPPCompiler):
class NvidiaHPC_CPPCompiler(PGICompiler, CPPCompiler):
+
+ id = 'nvidia_hpc'
+
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,
@@ -446,8 +460,6 @@ class NvidiaHPC_CPPCompiler(PGICompiler, CPPCompiler):
info, exe_wrapper, linker=linker, full_version=full_version)
PGICompiler.__init__(self)
- self.id = 'nvidia_hpc'
-
class ElbrusCPPCompiler(ElbrusCompiler, CPPCompiler):
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
@@ -687,6 +699,9 @@ class CPP11AsCPP14Mixin(CompilerMixinBase):
class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, MSVCCompiler, CPPCompiler):
+
+ id = 'msvc'
+
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,
@@ -695,7 +710,6 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, linker=linker, full_version=full_version)
MSVCCompiler.__init__(self, target)
- self.id = 'msvc'
def get_options(self) -> 'KeyedOptionDictType':
cpp_stds = ['none', 'c++11', 'vc++11']
@@ -727,6 +741,9 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
return args
class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, ClangClCompiler, CPPCompiler):
+
+ id = 'clang-cl'
+
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,
@@ -735,7 +752,6 @@ class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, Cl
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, linker=linker, full_version=full_version)
ClangClCompiler.__init__(self, target)
- self.id = 'clang-cl'
def get_options(self) -> 'KeyedOptionDictType':
cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest']
diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py
index 7ebb66d..b38f626 100644
--- a/mesonbuild/compilers/cs.py
+++ b/mesonbuild/compilers/cs.py
@@ -40,9 +40,8 @@ class CsCompiler(BasicLinkerIsCompilerMixin, Compiler):
language = 'cs'
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
- info: 'MachineInfo', comp_id: str, runner: T.Optional[str] = None):
+ info: 'MachineInfo', runner: T.Optional[str] = None):
super().__init__(exelist, version, for_machine, info)
- self.id = comp_id
self.runner = runner
@classmethod
@@ -121,19 +120,20 @@ class CsCompiler(BasicLinkerIsCompilerMixin, Compiler):
class MonoCompiler(CsCompiler):
+
+ id = 'mono'
+
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
info: 'MachineInfo'):
- super().__init__(exelist, version, for_machine, info, 'mono',
- runner='mono')
+ super().__init__(exelist, version, for_machine, info, runner='mono')
def rsp_file_syntax(self) -> 'RSPFileSyntax':
return RSPFileSyntax.GCC
class VisualStudioCsCompiler(CsCompiler):
- def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
- info: 'MachineInfo'):
- super().__init__(exelist, version, for_machine, info, 'csc')
+
+ id = 'csc'
def get_buildtype_args(self, buildtype: str) -> T.List[str]:
res = mono_buildtype_args[buildtype]
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 1f396e4..9662dbc 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -173,6 +173,8 @@ class CudaCompiler(Compiler):
# Reverse map -short to --long options.
_FLAG_SHORT2LONG_WITHARGS = {v: k for k, v in _FLAG_LONG2SHORT_WITHARGS.items()}
+ id = 'nvcc'
+
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, exe_wrapper: T.Optional['ExternalProgram'],
host_compiler: Compiler, info: 'MachineInfo',
@@ -182,7 +184,6 @@ class CudaCompiler(Compiler):
self.exe_wrapper = exe_wrapper
self.host_compiler = host_compiler
self.base_options = host_compiler.base_options
- self.id = 'nvcc'
self.warn_args = {level: self._to_host_flags(flags) for level, flags in host_compiler.warn_args.items()}
@classmethod
@@ -706,7 +707,7 @@ class CudaCompiler(Compiler):
return self._to_host_flags(self.host_compiler.get_buildtype_linker_args(buildtype), _Phase.LINKER)
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
(rpath_args, rpath_dirs_to_remove) = self.host_compiler.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index 4201d82..bae293e 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -249,7 +249,7 @@ class DmdLikeCompilerMixin(CompilerMixinBase):
return self.linker.import_library_args(implibname)
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if self.info.is_windows():
return ([], set())
@@ -681,6 +681,7 @@ class GnuDCompiler(GnuCompiler, DCompiler):
# we mostly want DCompiler, but that gives us the Compiler.LINKER_PREFIX instead
LINKER_PREFIX = GnuCompiler.LINKER_PREFIX
+ id = 'gcc'
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
info: 'MachineInfo', arch: str, *,
@@ -692,7 +693,6 @@ class GnuDCompiler(GnuCompiler, DCompiler):
exe_wrapper=exe_wrapper, linker=linker,
full_version=full_version, is_cross=is_cross)
GnuCompiler.__init__(self, {})
- self.id = 'gcc'
default_warn_args = ['-Wall', '-Wdeprecated']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -760,6 +760,8 @@ def find_ldc_dmd_frontend_version(version_output: T.Optional[str]) -> T.Optional
class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
+ id = 'llvm'
+
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
info: 'MachineInfo', arch: str, *,
exe_wrapper: T.Optional['ExternalProgram'] = None,
@@ -770,7 +772,6 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
exe_wrapper=exe_wrapper, linker=linker,
full_version=full_version, is_cross=is_cross)
DmdLikeCompilerMixin.__init__(self, dmd_frontend_version=find_ldc_dmd_frontend_version(version_output))
- self.id = 'llvm'
self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']}
def get_colorout_args(self, colortype: str) -> T.List[str]:
@@ -824,6 +825,8 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
+ id = 'dmd'
+
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
info: 'MachineInfo', arch: str, *,
exe_wrapper: T.Optional['ExternalProgram'] = None,
@@ -834,7 +837,6 @@ class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
exe_wrapper=exe_wrapper, linker=linker,
full_version=full_version, is_cross=is_cross)
DmdLikeCompilerMixin.__init__(self, version)
- self.id = 'dmd'
self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']}
def get_colorout_args(self, colortype: str) -> T.List[str]:
diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py
index 03c5226..572ec35 100644
--- a/mesonbuild/compilers/detect.py
+++ b/mesonbuild/compilers/detect.py
@@ -54,6 +54,7 @@ from .c import (
AppleClangCCompiler,
ArmCCompiler,
ArmclangCCompiler,
+ ArmLtdClangCCompiler,
ClangCCompiler,
ClangClCCompiler,
GnuCCompiler,
@@ -74,6 +75,7 @@ from .cpp import (
AppleClangCPPCompiler,
ArmCPPCompiler,
ArmclangCPPCompiler,
+ ArmLtdClangCPPCompiler,
ClangCPPCompiler,
ClangClCPPCompiler,
GnuCPPCompiler,
@@ -97,6 +99,7 @@ from .d import (
from .cuda import CudaCompiler
from .fortran import (
FortranCompiler,
+ ArmLtdFlangFortranCompiler,
G95FortranCompiler,
GnuFortranCompiler,
ElbrusFortranCompiler,
@@ -462,6 +465,20 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, linker=linker, full_version=full_version)
+ if 'Arm C/C++/Fortran Compiler' in out:
+ arm_ver_match = re.search('version (\d+)\.(\d+) \(build number (\d+)\)', out)
+ arm_ver_major = arm_ver_match.group(1)
+ arm_ver_minor = arm_ver_match.group(2)
+ arm_ver_build = arm_ver_match.group(3)
+ version = '.'.join([arm_ver_major, arm_ver_minor, arm_ver_build])
+ if lang == 'c':
+ cls = ArmLtdClangCCompiler
+ elif lang == 'cpp':
+ cls = ArmLtdClangCPPCompiler
+ linker = guess_nix_linker(env, compiler, cls, for_machine)
+ return cls(
+ ccache + compiler, version, for_machine, is_cross, info,
+ exe_wrap, linker=linker)
if 'armclang' in out:
# The compiler version is not present in the first line of output,
# instead it is present in second line, startswith 'Component:'.
@@ -711,6 +728,17 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C
compiler, version, for_machine, is_cross, info,
exe_wrap, defines, full_version=full_version, linker=linker)
+ if 'Arm C/C++/Fortran Compiler' in out:
+ cls = ArmLtdFlangFortranCompiler
+ arm_ver_match = re.search('version (\d+)\.(\d+) \(build number (\d+)\)', out)
+ arm_ver_major = arm_ver_match.group(1)
+ arm_ver_minor = arm_ver_match.group(2)
+ arm_ver_build = arm_ver_match.group(3)
+ version = '.'.join([arm_ver_major, arm_ver_minor, arm_ver_build])
+ linker = guess_nix_linker(env, compiler, cls, for_machine)
+ return cls(
+ ccache + compiler, version, for_machine, is_cross, info,
+ exe_wrap, linker=linker)
if 'G95' in out:
cls = G95FortranCompiler
linker = guess_nix_linker(env, compiler, cls, for_machine)
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 6a4a343..ba2454d 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -260,6 +260,7 @@ class ElbrusFortranCompiler(ElbrusCompiler, FortranCompiler):
class G95FortranCompiler(FortranCompiler):
LINKER_PREFIX = '-Wl,'
+ id = 'g95'
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
@@ -268,7 +269,6 @@ class G95FortranCompiler(FortranCompiler):
FortranCompiler.__init__(self, exelist, version, for_machine,
is_cross, info, exe_wrapper, linker=linker,
full_version=full_version)
- self.id = 'g95'
default_warn_args = ['-Wall']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -286,15 +286,7 @@ class G95FortranCompiler(FortranCompiler):
class SunFortranCompiler(FortranCompiler):
LINKER_PREFIX = '-Wl,'
-
- 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,
- full_version: T.Optional[str] = None):
- FortranCompiler.__init__(self, exelist, version, for_machine,
- is_cross, info, exe_wrapper, linker=linker,
- full_version=full_version)
- self.id = 'sun'
+ id = 'sun'
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return ['-fpp']
@@ -318,6 +310,7 @@ class SunFortranCompiler(FortranCompiler):
class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp', )
+ id = 'intel'
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool,
info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None,
@@ -329,7 +322,6 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
# FIXME: Add support for OS X and Windows in detect_fortran_compiler so
# we are sent the type of compiler
IntelGnuLikeCompiler.__init__(self)
- self.id = 'intel'
default_warn_args = ['-warn', 'general', '-warn', 'truncated_source']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -404,6 +396,8 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
class PathScaleFortranCompiler(FortranCompiler):
+ id = 'pathscale'
+
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,
@@ -411,7 +405,6 @@ class PathScaleFortranCompiler(FortranCompiler):
FortranCompiler.__init__(self, exelist, version, for_machine,
is_cross, info, exe_wrapper, linker=linker,
full_version=full_version)
- self.id = 'pathscale'
default_warn_args = ['-fullwarn']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -447,6 +440,8 @@ class PGIFortranCompiler(PGICompiler, FortranCompiler):
class NvidiaHPC_FortranCompiler(PGICompiler, FortranCompiler):
+ id = 'nvidia_hpc'
+
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,
@@ -456,7 +451,6 @@ class NvidiaHPC_FortranCompiler(PGICompiler, FortranCompiler):
full_version=full_version)
PGICompiler.__init__(self)
- self.id = 'nvidia_hpc'
default_warn_args = ['-Minform=inform']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -466,6 +460,8 @@ class NvidiaHPC_FortranCompiler(PGICompiler, FortranCompiler):
class FlangFortranCompiler(ClangCompiler, FortranCompiler):
+ id = 'flang'
+
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,
@@ -474,7 +470,6 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler):
is_cross, info, exe_wrapper, linker=linker,
full_version=full_version)
ClangCompiler.__init__(self, {})
- self.id = 'flang'
default_warn_args = ['-Minform=inform']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -494,8 +489,14 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler):
search_dirs.append(f'-L{d}')
return search_dirs + ['-lflang', '-lpgmath']
+class ArmLtdFlangFortranCompiler(FlangFortranCompiler):
+
+ id = 'armltdflang'
+
class Open64FortranCompiler(FortranCompiler):
+ id = 'open64'
+
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,
@@ -503,7 +504,6 @@ class Open64FortranCompiler(FortranCompiler):
FortranCompiler.__init__(self, exelist, version, for_machine,
is_cross, info, exe_wrapper, linker=linker,
full_version=full_version)
- self.id = 'open64'
default_warn_args = ['-fullwarn']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -516,6 +516,8 @@ class Open64FortranCompiler(FortranCompiler):
class NAGFortranCompiler(FortranCompiler):
+ id = 'nagfor'
+
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,
@@ -523,7 +525,6 @@ class NAGFortranCompiler(FortranCompiler):
FortranCompiler.__init__(self, exelist, version, for_machine,
is_cross, info, exe_wrapper, linker=linker,
full_version=full_version)
- self.id = 'nagfor'
# Warnings are on by default; -w disables (by category):
self.warn_args = {
'0': ['-w=all'],
diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py
index 4abf998..05c271a 100644
--- a/mesonbuild/compilers/java.py
+++ b/mesonbuild/compilers/java.py
@@ -30,11 +30,11 @@ if T.TYPE_CHECKING:
class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler):
language = 'java'
+ id = 'unknown'
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
info: 'MachineInfo', full_version: T.Optional[str] = None):
super().__init__(exelist, version, for_machine, info, full_version=full_version)
- self.id = 'unknown'
self.javarunner = 'java'
def get_werror_args(self) -> T.List[str]:
diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py
index 4e1898a..5bf862d 100644
--- a/mesonbuild/compilers/mixins/arm.py
+++ b/mesonbuild/compilers/mixins/arm.py
@@ -74,10 +74,11 @@ class ArmCompiler(Compiler):
"""Functionality that is common to all ARM family compilers."""
+ id = 'arm'
+
def __init__(self) -> None:
if not self.is_cross:
raise mesonlib.EnvironmentException('armcc supports only cross-compilation.')
- self.id = 'arm'
default_warn_args = [] # type: T.List[str]
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -136,6 +137,11 @@ class ArmCompiler(Compiler):
class ArmclangCompiler(Compiler):
+ '''
+ This is the Keil armclang.
+ '''
+
+ id = 'armclang'
def __init__(self) -> None:
if not self.is_cross:
@@ -145,7 +151,6 @@ class ArmclangCompiler(Compiler):
raise mesonlib.EnvironmentException(f'Unsupported Linker {self.linker.exelist}, must be armlink')
if not mesonlib.version_compare(self.version, '==' + self.linker.version):
raise mesonlib.EnvironmentException('armlink version does not match with compiler version')
- self.id = 'armclang'
self.base_options = {
OptionKey(o) for o in
['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
diff --git a/mesonbuild/compilers/mixins/c2000.py b/mesonbuild/compilers/mixins/c2000.py
index ab0278e..f614d16 100644
--- a/mesonbuild/compilers/mixins/c2000.py
+++ b/mesonbuild/compilers/mixins/c2000.py
@@ -55,10 +55,11 @@ c2000_debug_args = {
class C2000Compiler(Compiler):
+ id = 'c2000'
+
def __init__(self) -> None:
if not self.is_cross:
raise EnvironmentException('c2000 supports only cross-compilation.')
- self.id = 'c2000'
self.can_compile_suffixes.add('asm') # Assembly
self.can_compile_suffixes.add('cla') # Control Law Accelerator (CLA)
diff --git a/mesonbuild/compilers/mixins/ccrx.py b/mesonbuild/compilers/mixins/ccrx.py
index eba4c45..d87769e 100644
--- a/mesonbuild/compilers/mixins/ccrx.py
+++ b/mesonbuild/compilers/mixins/ccrx.py
@@ -59,10 +59,11 @@ class CcrxCompiler(Compiler):
is_cross = True
can_compile_suffixes = set() # type: T.Set[str]
+ id = 'ccrx'
+
def __init__(self) -> None:
if not self.is_cross:
raise EnvironmentException('ccrx supports only cross-compilation.')
- self.id = 'ccrx'
# Assembly
self.can_compile_suffixes.add('src')
default_warn_args = [] # type: T.List[str]
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index 1391297..663a87e 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -45,9 +45,10 @@ clang_optimization_args = {
class ClangCompiler(GnuLikeCompiler):
+ id = 'clang'
+
def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__()
- self.id = 'clang'
self.defines = defines or {}
self.base_options.update(
{OptionKey('b_colorout'), OptionKey('b_lto_threads'), OptionKey('b_lto_mode')})
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index 3d2df9b..269ce5c 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -437,7 +437,7 @@ class CLikeCompiler(Compiler):
dependencies = []
elif not isinstance(dependencies, collections.abc.Iterable):
# TODO: we want to ensure the front end does the listifing here
- dependencies = [dependencies] # type: ignore
+ dependencies = [dependencies]
# Collect compiler arguments
cargs = self.compiler_args() # type: arglist.CompilerArgs
largs = [] # type: T.List[str]
diff --git a/mesonbuild/compilers/mixins/compcert.py b/mesonbuild/compilers/mixins/compcert.py
index 3211f6a..283c043 100644
--- a/mesonbuild/compilers/mixins/compcert.py
+++ b/mesonbuild/compilers/mixins/compcert.py
@@ -60,8 +60,9 @@ ccomp_args_to_wul = [
class CompCertCompiler(Compiler):
+ id = 'ccomp'
+
def __init__(self) -> None:
- self.id = 'ccomp'
# Assembly
self.can_compile_suffixes.add('s')
default_warn_args = [] # type: T.List[str]
diff --git a/mesonbuild/compilers/mixins/elbrus.py b/mesonbuild/compilers/mixins/elbrus.py
index 80fbe12..aac9811 100644
--- a/mesonbuild/compilers/mixins/elbrus.py
+++ b/mesonbuild/compilers/mixins/elbrus.py
@@ -32,9 +32,10 @@ class ElbrusCompiler(GnuLikeCompiler):
# Elbrus compiler is nearly like GCC, but does not support
# PCH, LTO, sanitizers and color output as of version 1.21.x.
+ id = 'lcc'
+
def __init__(self) -> None:
super().__init__()
- self.id = 'lcc'
self.base_options = {OptionKey(o) for o in ['b_pgo', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']}
default_warn_args = ['-Wall']
self.warn_args = {'0': [],
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index bc40af4..ea3aab4 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -328,10 +328,10 @@ class GnuCompiler(GnuLikeCompiler):
GnuCompiler represents an actual GCC in its many incarnations.
Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC.
"""
+ id = 'gcc'
def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__()
- self.id = 'gcc'
self.defines = defines or {}
self.base_options.update({OptionKey('b_colorout'), OptionKey('b_lto_threads')})
diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py
index 1417743..2698b39 100644
--- a/mesonbuild/compilers/mixins/intel.py
+++ b/mesonbuild/compilers/mixins/intel.py
@@ -66,6 +66,7 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
'3': ['-O3'],
's': ['-Os'],
}
+ id = 'intel'
def __init__(self) -> None:
super().__init__()
@@ -77,7 +78,6 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
self.base_options = {mesonlib.OptionKey(o) for o in [
'b_pch', 'b_lundef', 'b_asneeded', 'b_pgo', 'b_coverage',
'b_ndebug', 'b_staticpic', 'b_pie']}
- self.id = 'intel'
self.lang_header = 'none'
def get_pch_suffix(self) -> str:
@@ -145,9 +145,7 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler):
's': ['/Os'],
}
- def __init__(self, target: str) -> None:
- super().__init__(target)
- self.id = 'intel-cl'
+ id = 'intel-cl'
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
args = super().get_compiler_check_args(mode)
diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py
index 144bc70..9513aa5 100644
--- a/mesonbuild/compilers/mixins/islinker.py
+++ b/mesonbuild/compilers/mixins/islinker.py
@@ -108,7 +108,7 @@ class BasicLinkerIsCompilerMixin(Compiler):
raise MesonException("This linker doesn't support soname args")
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return ([], set())
diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py
index 51de8af..2bc7012 100644
--- a/mesonbuild/compilers/mixins/pgi.py
+++ b/mesonbuild/compilers/mixins/pgi.py
@@ -43,9 +43,10 @@ pgi_buildtype_args = {
class PGICompiler(Compiler):
+ id = 'pgi'
+
def __init__(self) -> None:
self.base_options = {OptionKey('b_pch')}
- self.id = 'pgi'
default_warn_args = ['-Minform=inform']
self.warn_args = {'0': [],
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
index ddd5476..5118e41 100644
--- a/mesonbuild/compilers/mixins/visualstudio.py
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -388,9 +388,7 @@ class MSVCCompiler(VisualStudioLikeCompiler):
"""Specific to the Microsoft Compilers."""
- def __init__(self, target: str):
- super().__init__(target)
- self.id = 'msvc'
+ id = 'msvc'
def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]:
args = super().get_compile_debugfile_args(rel_obj, pch)
@@ -420,9 +418,10 @@ class ClangClCompiler(VisualStudioLikeCompiler):
"""Specific to Clang-CL."""
+ id = 'clang-cl'
+
def __init__(self, target: str):
super().__init__(target)
- self.id = 'clang-cl'
# Assembly
self.can_compile_suffixes.add('s')
@@ -439,6 +438,10 @@ class ClangClCompiler(VisualStudioLikeCompiler):
def get_pch_base_name(self, header: str) -> str:
return header
+ def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
+ if path == '':
+ path = '.'
+ return ['/clang:-isystem' + path] if is_system else ['-I' + path]
def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]:
if dep.get_include_type() == 'system':
@@ -450,4 +453,4 @@ class ClangClCompiler(VisualStudioLikeCompiler):
converted += [i]
return converted
else:
- return dep.get_compile_args() \ No newline at end of file
+ return dep.get_compile_args()
diff --git a/mesonbuild/compilers/mixins/xc16.py b/mesonbuild/compilers/mixins/xc16.py
index 77c4690..2433561 100644
--- a/mesonbuild/compilers/mixins/xc16.py
+++ b/mesonbuild/compilers/mixins/xc16.py
@@ -55,10 +55,11 @@ xc16_debug_args = {
class Xc16Compiler(Compiler):
+ id = 'xc16'
+
def __init__(self) -> None:
if not self.is_cross:
raise EnvironmentException('xc16 supports only cross-compilation.')
- self.id = 'xc16'
# Assembly
self.can_compile_suffixes.add('s')
default_warn_args = [] # type: T.List[str]
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index 8f7e165..399570d 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -44,6 +44,7 @@ class RustCompiler(Compiler):
# rustc doesn't invoke the compiler itself, it doesn't need a LINKER_PREFIX
language = 'rust'
+ id = 'rustc'
_WARNING_LEVELS: T.Dict[str, T.List[str]] = {
'0': ['-A', 'warnings'],
@@ -61,7 +62,6 @@ class RustCompiler(Compiler):
is_cross=is_cross, full_version=full_version,
linker=linker)
self.exe_wrapper = exe_wrapper
- self.id = 'rustc'
self.base_options.add(OptionKey('b_colorout'))
if 'link' in self.linker.id:
self.base_options.add(OptionKey('b_vscrt'))
@@ -205,11 +205,4 @@ class ClippyRustCompiler(RustCompiler):
This just provides us a different id
"""
- def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
- is_cross: bool, info: 'MachineInfo',
- exe_wrapper: T.Optional['ExternalProgram'] = None,
- full_version: T.Optional[str] = None,
- linker: T.Optional['DynamicLinker'] = None):
- super().__init__(exelist, version, for_machine, is_cross, info,
- exe_wrapper, full_version, linker)
- self.id = 'clippy-driver rustc'
+ id = 'clippy-driver rustc'
diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py
index 2d52e21..a2b57b8 100644
--- a/mesonbuild/compilers/swift.py
+++ b/mesonbuild/compilers/swift.py
@@ -37,6 +37,7 @@ class SwiftCompiler(Compiler):
LINKER_PREFIX = ['-Xlinker']
language = 'swift'
+ id = 'llvm'
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo', full_version: T.Optional[str] = None,
@@ -45,7 +46,6 @@ class SwiftCompiler(Compiler):
is_cross=is_cross, full_version=full_version,
linker=linker)
self.version = version
- self.id = 'llvm'
def needs_static_linker(self) -> bool:
return True
diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py
index b8144f6..7c3eac0 100644
--- a/mesonbuild/compilers/vala.py
+++ b/mesonbuild/compilers/vala.py
@@ -27,12 +27,12 @@ if T.TYPE_CHECKING:
class ValaCompiler(Compiler):
language = 'vala'
+ id = 'valac'
def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo'):
super().__init__(exelist, version, for_machine, info, is_cross=is_cross)
self.version = version
- self.id = 'valac'
self.base_options = {OptionKey('b_colorout')}
def needs_static_linker(self) -> bool:
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index f444cf1..2bb89a2 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -44,7 +44,10 @@ if T.TYPE_CHECKING:
CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], str]
# Check major_versions_differ() if changing versioning scheme.
-version = '0.60.99'
+#
+# Pip requires that RCs are named like this: '0.1.0.rc1'
+# But the corresponding Git tag needs to be '0.1.0rc1'
+version = '0.61.99'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode']
@@ -234,7 +237,7 @@ class UserArrayOption(UserOption[T.List[str]]):
elif isinstance(value, list):
newvalue = value
else:
- raise MesonException(f'"{newvalue}" should be a string array, but it is not')
+ raise MesonException(f'"{value}" should be a string array, but it is not')
return newvalue
def validate_value(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> T.List[str]:
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 6881a34..b79be42 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -27,9 +27,10 @@ from ..mesonlib import version_compare_many
from ..interpreterbase import FeatureDeprecated
if T.TYPE_CHECKING:
+ from .._typing import ImmutableListProtocol
from ..compilers.compilers import Compiler
from ..environment import Environment
- from ..build import BuildTarget, CustomTarget
+ from ..build import BuildTarget, CustomTarget, IncludeDirs
from ..mesonlib import FileOrString
@@ -162,7 +163,9 @@ class Dependency(HoldableObject):
def get_exe_args(self, compiler: 'Compiler') -> T.List[str]:
return []
- def get_pkgconfig_variable(self, variable_name: str, kwargs: T.Dict[str, T.Any]) -> str:
+ def get_pkgconfig_variable(self, variable_name: str,
+ define_variable: 'ImmutableListProtocol[str]',
+ default: T.Optional[str]) -> str:
raise DependencyException(f'{self.name!r} is not a pkgconfig dependency')
def get_configtool_variable(self, variable_name: str) -> str:
@@ -216,9 +219,10 @@ class Dependency(HoldableObject):
return new_dep
class InternalDependency(Dependency):
- def __init__(self, version: str, incdirs: T.List[str], compile_args: T.List[str],
- link_args: T.List[str], libraries: T.List['BuildTarget'],
- whole_libraries: T.List['BuildTarget'],
+ def __init__(self, version: str, incdirs: T.List['IncludeDirs'], compile_args: T.List[str],
+ link_args: T.List[str],
+ libraries: T.List[T.Union['BuildTarget', 'CustomTarget']],
+ whole_libraries: T.List[T.Union['BuildTarget', 'CustomTarget']],
sources: T.Sequence[T.Union['FileOrString', 'CustomTarget']],
ext_deps: T.List[Dependency], variables: T.Dict[str, T.Any]):
super().__init__(DependencyTypeName('internal'), {})
@@ -254,7 +258,9 @@ class InternalDependency(Dependency):
return True
return any(d.is_built() for d in self.ext_deps)
- def get_pkgconfig_variable(self, variable_name: str, kwargs: T.Dict[str, T.Any]) -> str:
+ def get_pkgconfig_variable(self, variable_name: str,
+ define_variable: 'ImmutableListProtocol[str]',
+ default: T.Optional[str]) -> str:
raise DependencyException('Method "get_pkgconfig_variable()" is '
'invalid for an internal dependency')
diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py
index aadf3f8..318bca2 100644
--- a/mesonbuild/dependencies/boost.py
+++ b/mesonbuild/dependencies/boost.py
@@ -648,7 +648,7 @@ class BoostDependency(SystemDependency):
try:
boost_pc = PkgConfigDependency('boost', self.env, {'required': False})
if boost_pc.found():
- boost_root = boost_pc.get_pkgconfig_variable('prefix', {'default': None})
+ boost_root = boost_pc.get_pkgconfig_variable('prefix', [], None)
if boost_root:
roots += [Path(boost_root)]
except DependencyException:
diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py
index a6898f8..dcbe5df 100644
--- a/mesonbuild/dependencies/cmake.py
+++ b/mesonbuild/dependencies/cmake.py
@@ -14,9 +14,9 @@
from .base import ExternalDependency, DependencyException, DependencyTypeName
from ..mesonlib import is_windows, MesonException, OptionKey, PerMachine, stringlistify, extract_as_list
-from ..mesondata import mesondata
from ..cmake import CMakeExecutor, CMakeTraceParser, CMakeException, CMakeToolchain, CMakeExecScope, check_cmake_args, CMakeTarget, resolve_cmake_trace_targets, cmake_is_debug
from .. import mlog
+import importlib.resources
from pathlib import Path
import functools
import re
@@ -583,7 +583,7 @@ class CMakeDependency(ExternalDependency):
shutil.rmtree(cmake_files.as_posix(), ignore_errors=True)
# Insert language parameters into the CMakeLists.txt and write new CMakeLists.txt
- cmake_txt = mesondata['dependencies/data/' + cmake_file].data
+ cmake_txt = importlib.resources.read_text('mesonbuild.dependencies.data', cmake_file, encoding = 'utf-8')
# In general, some Fortran CMake find_package() also require C language enabled,
# even if nothing from C is directly used. An easy Fortran example that fails
diff --git a/test cases/unit/98 install all targets/bar-devel.h b/mesonbuild/dependencies/data/__init__.py
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/bar-devel.h
+++ b/mesonbuild/dependencies/data/__init__.py
diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py
index 78ef9d6..2f1ed0a 100644
--- a/mesonbuild/dependencies/hdf5.py
+++ b/mesonbuild/dependencies/hdf5.py
@@ -164,7 +164,7 @@ def hdf5_factory(env: 'Environment', for_machine: 'MachineChoice',
if PCEXE:
# some distros put hdf5-1.2.3.pc with version number in .pc filename.
ret = subprocess.run([PCEXE, '--list-all'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
- universal_newlines=True)
+ text=True)
if ret.returncode == 0:
for pkg in ret.stdout.split('\n'):
if pkg.startswith('hdf5'):
diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py
index 8f4c639..e6921e9 100644
--- a/mesonbuild/dependencies/pkgconfig.py
+++ b/mesonbuild/dependencies/pkgconfig.py
@@ -24,6 +24,7 @@ import typing as T
if T.TYPE_CHECKING:
from ..environment import Environment
+ from .._typing import ImmutableListProtocol
class PkgConfigDependency(ExternalDependency):
# The class's copy of the pkg-config path. Avoids having to search for it
@@ -380,18 +381,13 @@ class PkgConfigDependency(ExternalDependency):
raise DependencyException(f'Could not generate libs for {self.name}:\n\n{out_raw}')
self.link_args, self.raw_link_args = self._search_libs(out, out_raw)
- def get_pkgconfig_variable(self, variable_name: str, kwargs: T.Dict[str, T.Union[str, T.List[str]]]) -> str:
+ def get_pkgconfig_variable(self, variable_name: str,
+ define_variable: 'ImmutableListProtocol[str]',
+ default: T.Optional[str]) -> str:
options = ['--variable=' + variable_name, self.name]
- if 'define_variable' in kwargs:
- definition = kwargs.get('define_variable', [])
- if not isinstance(definition, list):
- raise DependencyException('define_variable takes a list')
-
- if len(definition) != 2 or not all(isinstance(i, str) for i in definition):
- raise DependencyException('define_variable must be made up of 2 strings for VARIABLENAME and VARIABLEVALUE')
-
- options = ['--define-variable=' + '='.join(definition)] + options
+ if define_variable:
+ options = ['--define-variable=' + '='.join(define_variable)] + options
ret, out, err = self._call_pkgbin(options)
variable = ''
@@ -406,9 +402,8 @@ class PkgConfigDependency(ExternalDependency):
if not variable:
ret, out, _ = self._call_pkgbin(['--print-variables', self.name])
if not re.search(r'^' + variable_name + r'$', out, re.MULTILINE):
- if 'default' in kwargs:
- assert isinstance(kwargs['default'], str)
- variable = kwargs['default']
+ if default:
+ variable = default
else:
mlog.warning(f"pkgconfig variable '{variable_name}' not defined for dependency {self.name}.")
@@ -483,13 +478,8 @@ class PkgConfigDependency(ExternalDependency):
default_value: T.Optional[str] = None,
pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]:
if pkgconfig:
- kwargs: T.Dict[str, T.Union[str, T.List[str]]] = {}
- if default_value is not None:
- kwargs['default'] = default_value
- if pkgconfig_define is not None:
- kwargs['define_variable'] = pkgconfig_define
try:
- return self.get_pkgconfig_variable(pkgconfig, kwargs)
+ return self.get_pkgconfig_variable(pkgconfig, pkgconfig_define or [], default_value)
except DependencyException:
pass
if default_value is not None:
diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py
index 9dc928c..a004688 100644
--- a/mesonbuild/dependencies/qt.py
+++ b/mesonbuild/dependencies/qt.py
@@ -181,7 +181,7 @@ class QtPkgConfigDependency(_QtBase, PkgConfigDependency, metaclass=abc.ABCMeta)
self.is_found = False
return
if self.private_headers:
- qt_inc_dir = mod.get_pkgconfig_variable('includedir', {})
+ qt_inc_dir = mod.get_pkgconfig_variable('includedir', [], None)
mod_private_dir = os.path.join(qt_inc_dir, 'Qt' + m)
if not os.path.isdir(mod_private_dir):
# At least some versions of homebrew don't seem to set this
@@ -203,7 +203,7 @@ class QtPkgConfigDependency(_QtBase, PkgConfigDependency, metaclass=abc.ABCMeta)
if arg == f'-l{debug_lib_name}' or arg.endswith(f'{debug_lib_name}.lib') or arg.endswith(f'{debug_lib_name}.a'):
is_debug = True
break
- libdir = self.get_pkgconfig_variable('libdir', {})
+ libdir = self.get_pkgconfig_variable('libdir', [], None)
if not self._link_with_qtmain(is_debug, libdir):
self.is_found = False
return
@@ -211,7 +211,7 @@ class QtPkgConfigDependency(_QtBase, PkgConfigDependency, metaclass=abc.ABCMeta)
self.bindir = self.get_pkgconfig_host_bins(self)
if not self.bindir:
# If exec_prefix is not defined, the pkg-config file is broken
- prefix = self.get_pkgconfig_variable('exec_prefix', {})
+ prefix = self.get_pkgconfig_variable('exec_prefix', [], None)
if prefix:
self.bindir = os.path.join(prefix, 'bin')
@@ -387,7 +387,7 @@ class Qt4PkgConfigDependency(QtPkgConfigDependency):
applications = ['moc', 'uic', 'rcc', 'lupdate', 'lrelease']
for application in applications:
try:
- return os.path.dirname(core.get_pkgconfig_variable(f'{application}_location', {}))
+ return os.path.dirname(core.get_pkgconfig_variable(f'{application}_location', [], None))
except mesonlib.MesonException:
pass
return None
@@ -400,7 +400,7 @@ class Qt5PkgConfigDependency(QtPkgConfigDependency):
@staticmethod
def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
- return core.get_pkgconfig_variable('host_bins', {})
+ return core.get_pkgconfig_variable('host_bins', [], None)
def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
return _qt_get_private_includes(mod_inc_dir, module, self.version)
@@ -410,7 +410,7 @@ class Qt6PkgConfigDependency(QtPkgConfigDependency):
@staticmethod
def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str:
- return core.get_pkgconfig_variable('host_bins', {})
+ return core.get_pkgconfig_variable('host_bins', [], None)
def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]:
return _qt_get_private_includes(mod_inc_dir, module, self.version)
diff --git a/mesonbuild/depfile.py b/mesonbuild/depfile.py
index 62cbe81..a8b4588 100644
--- a/mesonbuild/depfile.py
+++ b/mesonbuild/depfile.py
@@ -11,12 +11,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import collections
+import typing as T
-def parse(lines):
- rules = []
- targets = []
- deps = []
+
+def parse(lines: T.Iterable[str]) -> T.List[T.Tuple[T.List[str], T.List[str]]]:
+ rules: T.List[T.Tuple[T.List[str], T.List[str]]] = []
+ targets: T.List[str] = []
+ deps: T.List[str] = []
in_deps = False
out = ''
for line in lines:
@@ -56,12 +57,15 @@ def parse(lines):
out += c
return rules
-Target = collections.namedtuple('Target', ['deps'])
+class Target(T.NamedTuple):
+
+ deps: T.Set[str]
+
class DepFile:
- def __init__(self, lines):
+ def __init__(self, lines: T.Iterable[str]):
rules = parse(lines)
- depfile = {}
+ depfile: T.Dict[str, Target] = {}
for (targets, deps) in rules:
for target in targets:
t = depfile.setdefault(target, Target(deps=set()))
@@ -69,16 +73,17 @@ class DepFile:
t.deps.add(dep)
self.depfile = depfile
- def get_all_dependencies(self, target, visited=None):
- deps = set()
+ def get_all_dependencies(self, name: str, visited: T.Optional[T.Set[str]] = None) -> T.List[str]:
+ deps: T.Set[str] = set()
if not visited:
visited = set()
- if target in visited:
- return set()
- visited.add(target)
- target = self.depfile.get(target)
+ if name in visited:
+ return []
+ visited.add(name)
+
+ target = self.depfile.get(name)
if not target:
- return set()
+ return []
deps.update(target.deps)
for dep in target.deps:
deps.update(self.get_all_dependencies(dep, visited))
diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py
index 3a2923b..1b5f728 100644
--- a/mesonbuild/envconfig.py
+++ b/mesonbuild/envconfig.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from dataclasses import dataclass
import subprocess
import typing as T
from enum import Enum
@@ -234,27 +235,15 @@ class Properties:
def get(self, key: str, default: T.Optional[T.Union[str, bool, int, T.List[str]]] = None) -> T.Optional[T.Union[str, bool, int, T.List[str]]]:
return self.properties.get(key, default)
+@dataclass(unsafe_hash=True)
class MachineInfo(HoldableObject):
- def __init__(self, system: str, cpu_family: str, cpu: str, endian: str):
- self.system = system
- self.cpu_family = cpu_family
- self.cpu = cpu
- self.endian = endian
- self.is_64_bit = cpu_family in CPU_FAMILIES_64_BIT # type: bool
+ system: str
+ cpu_family: str
+ cpu: str
+ endian: str
- def __eq__(self, other: object) -> bool:
- if not isinstance(other, MachineInfo):
- return NotImplemented
- return \
- self.system == other.system and \
- self.cpu_family == other.cpu_family and \
- self.cpu == other.cpu and \
- self.endian == other.endian
-
- def __ne__(self, other: object) -> bool:
- if not isinstance(other, MachineInfo):
- return NotImplemented
- return not self.__eq__(other)
+ def __post_init__(self) -> None:
+ self.is_64_bit: bool = self.cpu_family in CPU_FAMILIES_64_BIT
def __repr__(self) -> str:
return f'<MachineInfo: {self.system} {self.cpu_family} ({self.cpu})>'
diff --git a/mesonbuild/interpreter/__init__.py b/mesonbuild/interpreter/__init__.py
index 2269837..016e4dc 100644
--- a/mesonbuild/interpreter/__init__.py
+++ b/mesonbuild/interpreter/__init__.py
@@ -28,7 +28,7 @@ __all__ = [
'CustomTargetIndexHolder',
'MachineHolder',
'Test',
- 'ConfigurationDataObject',
+ 'ConfigurationDataHolder',
'SubprojectHolder',
'DependencyHolder',
'GeneratedListHolder',
@@ -46,7 +46,7 @@ from .interpreter import Interpreter, permitted_dependency_kwargs
from .compiler import CompilerHolder
from .interpreterobjects import (ExecutableHolder, BuildTargetHolder, CustomTargetHolder,
CustomTargetIndexHolder, MachineHolder, Test,
- ConfigurationDataObject, SubprojectHolder, DependencyHolder,
+ ConfigurationDataHolder, SubprojectHolder, DependencyHolder,
GeneratedListHolder, ExternalProgramHolder,
extract_required_kwarg)
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index d4dbec9..bd71f78 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -43,7 +43,6 @@ from .mesonmain import MesonMain
from .dependencyfallbacks import DependencyFallbacksHolder
from .interpreterobjects import (
SubprojectHolder,
- ConfigurationDataObject,
Test,
RunProcess,
extract_required_kwarg,
@@ -433,6 +432,7 @@ class Interpreter(InterpreterBase, HoldableObject):
dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder,
coredata.UserFeatureOption: OBJ.FeatureOptionHolder,
envconfig.MachineInfo: OBJ.MachineHolder,
+ build.ConfigurationData: OBJ.ConfigurationDataHolder,
})
'''
@@ -488,7 +488,7 @@ class Interpreter(InterpreterBase, HoldableObject):
elif isinstance(v, Test):
self.build.tests.append(v)
elif isinstance(v, (int, str, bool, Disabler, ObjectHolder, build.GeneratedList,
- ExternalProgram)):
+ ExternalProgram, build.ConfigurationData)):
pass
else:
raise InterpreterException(f'Module returned a value of unknown type {v!r}.')
@@ -829,6 +829,11 @@ external dependencies (including libraries) must go to "dependencies".''')
subproject = self.subprojects[subp_name]
if required and not subproject.found():
raise InterpreterException(f'Subproject "{subproject.subdir}" required but not found.')
+ if 'version' in kwargs:
+ pv = self.build.subprojects[subp_name]
+ wanted = kwargs['version']
+ if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]:
+ raise InterpreterException(f'Subproject {subp_name} version is {pv} but {wanted} required.')
return subproject
r = self.environment.wrap_resolver
@@ -1015,13 +1020,16 @@ external dependencies (including libraries) must go to "dependencies".''')
@typed_pos_args('configuration_data', optargs=[dict])
@noKwargs
- def func_configuration_data(self, node: mparser.BaseNode, args: T.Optional[dict], kwargs: 'TYPE_kwargs') -> ConfigurationDataObject:
+ def func_configuration_data(self, node: mparser.BaseNode, args: T.Tuple[T.Optional[T.Dict[str, T.Any]]],
+ kwargs: 'TYPE_kwargs') -> build.ConfigurationData:
initial_values = args[0]
if initial_values is not None:
FeatureNew.single_use('configuration_data dictionary', '0.49.0', self.subproject)
- else:
- initial_values = {}
- return ConfigurationDataObject(self.subproject, initial_values)
+ for k, v in initial_values.items():
+ if not isinstance(v, (str, int ,bool)):
+ raise InvalidArguments(
+ f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"')
+ return build.ConfigurationData(initial_values)
def set_backend(self):
# The backend is already set when parsing subprojects
@@ -1445,9 +1453,10 @@ external dependencies (including libraries) must go to "dependencies".''')
progobj = self.notfound_program(args)
if isinstance(progobj, ExternalProgram) and not progobj.found():
- mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'))
+ if not silent:
+ mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'))
if required:
- m = 'Program {!r} not found'
+ m = 'Program {!r} not found or not executable'
raise InterpreterException(m.format(progobj.get_name()))
return progobj
@@ -1475,7 +1484,8 @@ external dependencies (including libraries) must go to "dependencies".''')
# Only store successful lookups
self.store_name_lookups(args)
- mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.green('YES'), *extra_info)
+ if not silent:
+ mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.green('YES'), *extra_info)
if isinstance(progobj, build.Executable):
progobj.was_returned_by_find_program = True
return progobj
@@ -2228,8 +2238,12 @@ external dependencies (including libraries) must go to "dependencies".''')
conf = kwargs['configuration']
if isinstance(conf, dict):
FeatureNew.single_use('configure_file.configuration dictionary', '0.49.0', self.subproject)
- conf = ConfigurationDataObject(self.subproject, conf)
- elif not isinstance(conf, ConfigurationDataObject):
+ for k, v in conf.items():
+ if not isinstance(v, (str, int ,bool)):
+ raise InvalidArguments(
+ f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"')
+ conf = build.ConfigurationData(conf)
+ elif not isinstance(conf, build.ConfigurationData):
raise InterpreterException('Argument "configuration" is not of type configuration_data')
mlog.log('Configuring', mlog.bold(output), 'using configuration')
if len(inputs) > 1:
@@ -2238,7 +2252,7 @@ external dependencies (including libraries) must go to "dependencies".''')
os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
file_encoding = kwargs.setdefault('encoding', 'utf-8')
missing_variables, confdata_useless = \
- mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf.conf_data,
+ mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf,
fmt, file_encoding)
if missing_variables:
var_list = ", ".join(map(repr, sorted(missing_variables)))
@@ -2254,8 +2268,8 @@ external dependencies (including libraries) must go to "dependencies".''')
'copy a file to the build dir, use the \'copy:\' keyword '
'argument added in 0.47.0', location=node)
else:
- mesonlib.dump_conf_header(ofile_abs, conf.conf_data, output_format)
- conf.mark_used()
+ mesonlib.dump_conf_header(ofile_abs, conf, output_format)
+ conf.used = True
elif 'command' in kwargs:
if len(inputs) > 1:
FeatureNew.single_use('multiple inputs in configure_file()', '0.52.0', self.subproject)
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index f078698..9560221 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -16,8 +16,8 @@ from ..backend.backends import TestProtocol
from ..interpreterbase import (
ContainerTypeInfo, KwargInfo, MesonOperator,
InterpreterObject, MesonInterpreterObject, ObjectHolder, MutableInterpreterObject,
- FeatureCheckBase, FeatureNewKwargs, FeatureNew, FeatureDeprecated,
- typed_pos_args, typed_kwargs, typed_operator, permittedKwargs,
+ FeatureCheckBase, FeatureNew, FeatureDeprecated,
+ typed_pos_args, typed_kwargs, typed_operator,
noArgsFlattening, noPosargs, noKwargs, unholder_return, TYPE_var, TYPE_kwargs, TYPE_nvar, TYPE_nkwargs,
flatten, resolve_second_level_holders, InterpreterException, InvalidArguments, InvalidCode)
from ..interpreter.type_checking import NoneType
@@ -124,32 +124,25 @@ class FeatureOptionHolder(ObjectHolder[coredata.UserFeatureOption]):
def auto_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value == 'auto'
- @permittedKwargs({'error_message'})
- def require_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption:
- if len(args) != 1:
- raise InvalidArguments(f'Expected 1 argument, got {len(args)}.')
- if not isinstance(args[0], bool):
- raise InvalidArguments('boolean argument expected.')
- error_message = kwargs.pop('error_message', '')
- if error_message and not isinstance(error_message, str):
- raise InterpreterException("Error message must be a string.")
+ @typed_pos_args('feature_option.require', bool)
+ @typed_kwargs(
+ 'feature_option.require',
+ KwargInfo('error_message', (str, NoneType))
+ )
+ def require_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> coredata.UserFeatureOption:
if args[0]:
return copy.deepcopy(self.held_object)
- assert isinstance(error_message, str)
if self.value == 'enabled':
- prefix = f'Feature {self.held_object.name} cannot be enabled'
- if error_message:
- prefix += ': '
- raise InterpreterException(prefix + error_message)
+ err_msg = f'Feature {self.held_object.name} cannot be enabled'
+ if kwargs['error_message']:
+ err_msg += f': {kwargs["error_message"]}'
+ raise InterpreterException(err_msg)
return self.as_disabled()
@noKwargs
- def disable_auto_if_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption:
- if len(args) != 1:
- raise InvalidArguments(f'Expected 1 argument, got {len(args)}.')
- if not isinstance(args[0], bool):
- raise InvalidArguments('boolean argument expected.')
+ @typed_pos_args('feature_option.disable_auto_if', bool)
+ def disable_auto_if_method(self, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption:
return copy.deepcopy(self.held_object) if self.value != 'auto' or not args[0] else self.as_disabled()
@@ -283,11 +276,13 @@ class EnvironmentVariablesHolder(ObjectHolder[build.EnvironmentVariables], Mutab
self.held_object.prepend(name, values, kwargs['separator'])
-class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
- def __init__(self, subproject: str, initial_values: T.Optional[T.Dict[str, T.Any]] = None) -> None:
- self.used = False # These objects become immutable after use in configure_file.
- super().__init__(subproject=subproject)
- self.conf_data = build.ConfigurationData()
+_CONF_DATA_SET_KWS: KwargInfo[T.Optional[str]] = KwargInfo('description', (str, NoneType))
+
+
+class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInterpreterObject):
+
+ def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'):
+ super().__init__(obj, interpreter)
self.methods.update({'set': self.set_method,
'set10': self.set10_method,
'set_quoted': self.set_quoted_method,
@@ -297,97 +292,70 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
'get_unquoted': self.get_unquoted_method,
'merge_from': self.merge_from_method,
})
- if isinstance(initial_values, dict):
- for k, v in initial_values.items():
- self.set_method([k, v], {})
- elif initial_values:
- raise AssertionError('Unsupported ConfigurationDataObject initial_values')
+
+ def __deepcopy__(self, memo: T.Dict) -> 'ConfigurationDataHolder':
+ return ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter)
def is_used(self) -> bool:
- return self.used
-
- def mark_used(self) -> None:
- self.used = True
-
- def validate_args(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Tuple[str, T.Union[str, int, bool], T.Optional[str]]:
- if len(args) == 1 and isinstance(args[0], list) and len(args[0]) == 2:
- mlog.deprecation('Passing a list as the single argument to '
- 'configuration_data.set is deprecated. This will '
- 'become a hard error in the future.',
- location=self.current_node)
- args = args[0]
-
- if len(args) != 2:
- raise InterpreterException("Configuration set requires 2 arguments.")
- if self.used:
- raise InterpreterException("Can not set values on configuration object that has been used.")
- name, val = args
- if not isinstance(val, (int, str)):
- msg = f'Setting a configuration data value to {val!r} is invalid, ' \
- 'and will fail at configure_file(). If you are using it ' \
- 'just to store some values, please use a dict instead.'
- mlog.deprecation(msg, location=self.current_node)
- desc = kwargs.get('description', None)
- if not isinstance(name, str):
- raise InterpreterException("First argument to set must be a string.")
- if desc is not None and not isinstance(desc, str):
- raise InterpreterException('Description must be a string.')
-
- # TODO: Remove the cast once we get rid of the deprecation
- return name, T.cast(T.Union[str, bool, int], val), desc
+ return self.held_object.used
- @noArgsFlattening
- def set_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
- (name, val, desc) = self.validate_args(args, kwargs)
- self.conf_data.values[name] = (val, desc)
-
- def set_quoted_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
- (name, val, desc) = self.validate_args(args, kwargs)
- if not isinstance(val, str):
- raise InterpreterException("Second argument to set_quoted must be a string.")
- escaped_val = '\\"'.join(val.split('"'))
- self.conf_data.values[name] = ('"' + escaped_val + '"', desc)
-
- def set10_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
- (name, val, desc) = self.validate_args(args, kwargs)
- if val:
- self.conf_data.values[name] = (1, desc)
- else:
- self.conf_data.values[name] = (0, desc)
+ def __check_used(self) -> None:
+ if self.is_used():
+ raise InterpreterException("Can not set values on configuration object that has been used.")
- def has_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
- return args[0] in self.conf_data.values
+ @typed_pos_args('configuration_data.set', str, (str, int, bool))
+ @typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS)
+ def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
+ self.__check_used()
+ self.held_object.values[args[0]] = (args[1], kwargs['description'])
+
+ @typed_pos_args('configuration_data.set_quoted', str, str)
+ @typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS)
+ def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None:
+ self.__check_used()
+ escaped_val = '\\"'.join(args[1].split('"'))
+ self.held_object.values[args[0]] = (f'"{escaped_val}"', kwargs['description'])
+
+ @typed_pos_args('configuration_data.set10', str, (int, bool))
+ @typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS)
+ def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
+ self.__check_used()
+ if isinstance(args[1], int):
+ mlog.deprecation('configuration_data.set10 with number. the `set10` '
+ 'method should only be used with booleans',
+ location=self.interpreter.current_node)
+ if args[1] < 0:
+ mlog.warning('Passing a number that is less than 0 may not have the intended result, '
+ 'as meson will treat all non-zero values as true.',
+ location=self.interpreter.current_node)
+ self.held_object.values[args[0]] = (int(args[1]), kwargs['description'])
+
+ @typed_pos_args('configuration_data.has', (str, int, bool))
+ @noKwargs
+ def has_method(self, args: T.Tuple[T.Union[str, int, bool]], kwargs: TYPE_kwargs) -> bool:
+ return args[0] in self.held_object.values
@FeatureNew('configuration_data.get()', '0.38.0')
- @noArgsFlattening
- def get_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
- if len(args) < 1 or len(args) > 2:
- raise InterpreterException('Get method takes one or two arguments.')
- if not isinstance(args[0], str):
- raise InterpreterException('The variable name must be a string.')
+ @typed_pos_args('configuration_data.get', str, optargs=[(str, int, bool)])
+ @noKwargs
+ def get_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]],
+ kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
name = args[0]
- if name in self.conf_data:
- return self.conf_data.get(name)[0]
- if len(args) > 1:
- # Assertion does not work because setting other values is still
- # supported, but deprecated. Use T.cast in the meantime (even though
- # this is a lie).
- # TODO: Fix this once the deprecation is removed
- # assert isinstance(args[1], (int, str, bool))
- return T.cast(T.Union[str, int, bool], args[1])
+ if name in self.held_object:
+ return self.held_object.get(name)[0]
+ elif args[1] is not None:
+ return args[1]
raise InterpreterException(f'Entry {name} not in configuration data.')
@FeatureNew('configuration_data.get_unquoted()', '0.44.0')
- def get_unquoted_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
- if len(args) < 1 or len(args) > 2:
- raise InterpreterException('Get method takes one or two arguments.')
- if not isinstance(args[0], str):
- raise InterpreterException('The variable name must be a string.')
+ @typed_pos_args('configuration_data.get_unquoted', str, optargs=[(str, int, bool)])
+ @noKwargs
+ def get_unquoted_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]],
+ kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
name = args[0]
- if name in self.conf_data:
- val = self.conf_data.get(name)[0]
- elif len(args) > 1:
- assert isinstance(args[1], (str, int, bool))
+ if name in self.held_object:
+ val = self.held_object.get(name)[0]
+ elif args[1] is not None:
val = args[1]
else:
raise InterpreterException(f'Entry {name} not in configuration data.')
@@ -396,25 +364,22 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
return val
def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]:
- return self.conf_data.values[name]
+ return self.held_object.values[name]
@FeatureNew('configuration_data.keys()', '0.57.0')
@noPosargs
+ @noKwargs
def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]:
return sorted(self.keys())
def keys(self) -> T.List[str]:
- return list(self.conf_data.values.keys())
+ return list(self.held_object.values.keys())
- def merge_from_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
- if len(args) != 1:
- raise InterpreterException('Merge_from takes one positional argument.')
- from_object_holder = args[0]
- if not isinstance(from_object_holder, ConfigurationDataObject):
- raise InterpreterException('Merge_from argument must be a configuration data object.')
- from_object = from_object_holder.conf_data
- for k, v in from_object.values.items():
- self.conf_data.values[k] = v
+ @typed_pos_args('configuration_data.merge_from', build.ConfigurationData)
+ @noKwargs
+ def merge_from_method(self, args: T.Tuple[build.ConfigurationData], kwargs: TYPE_kwargs) -> None:
+ from_object = args[0]
+ self.held_object.values.update(from_object.values)
_PARTIAL_DEP_KWARGS = [
@@ -466,71 +431,75 @@ class DependencyHolder(ObjectHolder[Dependency]):
def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_name()
- @FeatureDeprecated('Dependency.get_pkgconfig_variable', '0.56.0',
- 'use Dependency.get_variable(pkgconfig : ...) instead')
- @permittedKwargs({'define_variable', 'default'})
- def pkgconfig_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
- args = listify(args)
- if len(args) != 1:
- raise InterpreterException('get_pkgconfig_variable takes exactly one argument.')
- varname = args[0]
- if not isinstance(varname, str):
- raise InterpreterException('Variable name must be a string.')
- return self.held_object.get_pkgconfig_variable(varname, kwargs)
+ @FeatureDeprecated('dependency.get_pkgconfig_variable', '0.56.0',
+ 'use dependency.get_variable(pkgconfig : ...) instead')
+ @typed_pos_args('dependency.get_pkgconfig_variable', str)
+ @typed_kwargs(
+ 'dependency.get_pkgconfig_variable',
+ KwargInfo('default', (str, NoneType)),
+ KwargInfo(
+ 'define_variable',
+ ContainerTypeInfo(list, str, pairs=True),
+ default=[],
+ listify=True,
+ validator=lambda x: 'must be of length 2 or empty' if len(x) not in {0, 2} else None,
+ ),
+ )
+ def pkgconfig_method(self, args: T.Tuple[str], kwargs: 'kwargs.DependencyPkgConfigVar') -> str:
+ return self.held_object.get_pkgconfig_variable(args[0], **kwargs)
- @FeatureNew('dep.get_configtool_variable', '0.44.0')
- @FeatureDeprecated('Dependency.get_configtool_variable', '0.56.0',
- 'use Dependency.get_variable(configtool : ...) instead')
+ @FeatureNew('dependency.get_configtool_variable', '0.44.0')
+ @FeatureDeprecated('dependency.get_configtool_variable', '0.56.0',
+ 'use dependency.get_variable(configtool : ...) instead')
@noKwargs
- def configtool_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
- args = listify(args)
- if len(args) != 1:
- raise InterpreterException('get_configtool_variable takes exactly one argument.')
- varname = args[0]
- if not isinstance(varname, str):
- raise InterpreterException('Variable name must be a string.')
- return self.held_object.get_configtool_variable(varname)
+ @typed_pos_args('dependency.get_config_tool_variable', str)
+ def configtool_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> str:
+ return self.held_object.get_configtool_variable(args[0])
- @FeatureNew('dep.partial_dependency', '0.46.0')
+ @FeatureNew('dependency.partial_dependency', '0.46.0')
@noPosargs
- @typed_kwargs('dep.partial_dependency', *_PARTIAL_DEP_KWARGS)
+ @typed_kwargs('dependency.partial_dependency', *_PARTIAL_DEP_KWARGS)
def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency:
pdep = self.held_object.get_partial_dependency(**kwargs)
return pdep
- @FeatureNew('dep.get_variable', '0.51.0')
- @typed_pos_args('dep.get_variable', optargs=[str])
- @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'internal', 'default_value', 'pkgconfig_define'})
- @FeatureNewKwargs('dep.get_variable', '0.54.0', ['internal'])
- def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: T.Dict[str, T.Any]) -> T.Union[str, T.List[str]]:
+ @FeatureNew('dependency.get_variable', '0.51.0')
+ @typed_pos_args('dependency.get_variable', optargs=[str])
+ @typed_kwargs(
+ 'dependency.get_variable',
+ KwargInfo('cmake', (str, NoneType)),
+ KwargInfo('pkgconfig', (str, NoneType)),
+ KwargInfo('configtool', (str, NoneType)),
+ KwargInfo('internal', (str, NoneType), since='0.54.0'),
+ KwargInfo('default_value', (str, NoneType)),
+ KwargInfo('pkgconfig_define', ContainerTypeInfo(list, str, pairs=True), default=[], listify=True),
+ )
+ def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> T.Union[str, T.List[str]]:
default_varname = args[0]
if default_varname is not None:
- FeatureNew('Positional argument to dep.get_variable()', '0.58.0', location=self.current_node).use(self.subproject)
- for k in ['cmake', 'pkgconfig', 'configtool', 'internal']:
- kwargs.setdefault(k, default_varname)
- return self.held_object.get_variable(**kwargs)
+ FeatureNew('Positional argument to dependency.get_variable()', '0.58.0', location=self.current_node).use(self.subproject)
+ return self.held_object.get_variable(
+ cmake=kwargs['cmake'] or default_varname,
+ pkgconfig=kwargs['pkgconfig'] or default_varname,
+ configtool=kwargs['configtool'] or default_varname,
+ internal=kwargs['internal'] or default_varname,
+ default_value=kwargs['default_value'],
+ pkgconfig_define=kwargs['pkgconfig_define'],
+ )
- @FeatureNew('dep.include_type', '0.52.0')
+ @FeatureNew('dependency.include_type', '0.52.0')
@noPosargs
@noKwargs
def include_type_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_include_type()
- @FeatureNew('dep.as_system', '0.52.0')
- @noKwargs
- def as_system_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> Dependency:
- args = listify(args)
- new_is_system = 'system'
- if len(args) > 1:
- raise InterpreterException('as_system takes only one optional value')
- if len(args) == 1:
- if not isinstance(args[0], str):
- raise InterpreterException('as_system takes exactly one string parameter')
- new_is_system = args[0]
- new_dep = self.held_object.generate_system_dependency(new_is_system)
- return new_dep
+ @FeatureNew('dependency.as_system', '0.52.0')
+ @noKwargs
+ @typed_pos_args('dependency.as_system', optargs=[str])
+ def as_system_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> Dependency:
+ return self.held_object.generate_system_dependency(args[0] or 'system')
- @FeatureNew('dep.as_link_whole', '0.56.0')
+ @FeatureNew('dependency.as_link_whole', '0.56.0')
@noKwargs
@noPosargs
def as_link_whole_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> Dependency:
@@ -592,9 +561,9 @@ class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.held_object.found()
- @FeatureNew('dep.partial_dependency', '0.46.0')
+ @FeatureNew('dependency.partial_dependency', '0.46.0')
@noPosargs
- @typed_kwargs('dep.partial_dependency', *_PARTIAL_DEP_KWARGS)
+ @typed_kwargs('dependency.partial_dependency', *_PARTIAL_DEP_KWARGS)
def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency:
pdep = self.held_object.get_partial_dependency(**kwargs)
return pdep
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index 6056329..777db12 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -239,3 +239,30 @@ class RunCommand(TypedDict):
check: bool
capture: T.Optional[bool]
env: build.EnvironmentVariables
+
+
+class FeatureOptionRequire(TypedDict):
+
+ error_message: T.Optional[str]
+
+
+class DependencyPkgConfigVar(TypedDict):
+
+ default: T.Optional[str]
+ define_variable: T.List[str]
+
+
+
+class DependencyGetVariable(TypedDict):
+
+ cmake: T.Optional[str]
+ pkgconfig: T.Optional[str]
+ configtool: T.Optional[str]
+ internal: T.Optional[str]
+ default_value: T.Optional[str]
+ pkgconfig_define: T.List[str]
+
+
+class ConfigurationDataSet(TypedDict):
+
+ description: T.Optional[str]
diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py
index e973c5d..be1acc6 100644
--- a/mesonbuild/interpreter/mesonmain.py
+++ b/mesonbuild/interpreter/mesonmain.py
@@ -79,13 +79,19 @@ class MesonMain(MesonInterpreterObject):
})
def _find_source_script(
- self, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram],
+ self, name: str, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram],
args: T.List[str]) -> 'ExecutableSerialisation':
largs: T.List[T.Union[str, build.Executable, ExternalProgram]] = []
+
if isinstance(prog, (build.Executable, ExternalProgram)):
+ FeatureNew.single_use(f'Passing executable/found program object to script parameter of {name}',
+ '0.55.0', self.subproject, location=self.current_node)
largs.append(prog)
largs.extend(args)
return self.interpreter.backend.get_executable_serialisation(largs)
+ elif isinstance(prog, mesonlib.File):
+ FeatureNew.single_use(f'Passing file object to script parameter of {name}',
+ '0.57.0', self.subproject, location=self.current_node)
found = self.interpreter.find_program_impl([prog])
largs.append(found)
largs.extend(args)
@@ -98,7 +104,7 @@ class MesonMain(MesonInterpreterObject):
str, mesonlib.File, build.BuildTarget, build.CustomTarget,
build.CustomTargetIndex,
ExternalProgram,
- ]], allow_built: bool = False) -> T.List[str]:
+ ]]) -> T.List[str]:
script_args = [] # T.List[str]
new = False
for a in args:
@@ -108,8 +114,6 @@ class MesonMain(MesonInterpreterObject):
new = True
script_args.append(a.rel_to_builddir(self.interpreter.environment.source_dir))
elif isinstance(a, (build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)):
- if not allow_built:
- raise InterpreterException(f'Arguments to {name} cannot be built')
new = True
script_args.extend([os.path.join(a.get_subdir(), o) for o in a.get_outputs()])
@@ -147,12 +151,8 @@ class MesonMain(MesonInterpreterObject):
args: T.Tuple[T.Union[str, mesonlib.File, build.Executable, ExternalProgram],
T.List[T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, ExternalProgram]]],
kwargs: 'AddInstallScriptKW') -> None:
- if isinstance(args[0], mesonlib.File):
- FeatureNew.single_use('Passing file object to script parameter of add_install_script',
- '0.57.0', self.interpreter.subproject)
-
- script_args = self._process_script_args('add_install_script', args[1], allow_built=True)
- script = self._find_source_script(args[0], script_args)
+ script_args = self._process_script_args('add_install_script', args[1])
+ script = self._find_source_script('add_install_script', args[0], script_args)
script.skip_if_destdir = kwargs['skip_if_destdir']
script.tag = kwargs['install_tag']
self.build.install_scripts.append(script)
@@ -160,43 +160,37 @@ class MesonMain(MesonInterpreterObject):
@typed_pos_args(
'meson.add_postconf_script',
(str, mesonlib.File, ExternalProgram),
- varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)
+ varargs=(str, mesonlib.File, ExternalProgram)
)
@noKwargs
def add_postconf_script_method(
self,
args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram],
- T.List[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]],
+ T.List[T.Union[str, mesonlib.File, ExternalProgram]]],
kwargs: 'TYPE_kwargs') -> None:
- if isinstance(args[0], mesonlib.File):
- FeatureNew.single_use('Passing file object to script parameter of add_postconf_script',
- '0.57.0', self.interpreter.subproject)
- script_args = self._process_script_args('add_postconf_script', args[1], allow_built=True)
- script = self._find_source_script(args[0], script_args)
+ script_args = self._process_script_args('add_postconf_script', args[1])
+ script = self._find_source_script('add_postconf_script', args[0], script_args)
self.build.postconf_scripts.append(script)
@typed_pos_args(
'meson.add_dist_script',
- (str, mesonlib.File, build.Executable, ExternalProgram),
- varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)
+ (str, mesonlib.File, ExternalProgram),
+ varargs=(str, mesonlib.File, ExternalProgram)
)
@noKwargs
def add_dist_script_method(
self,
- args: T.Tuple[T.Union[str, mesonlib.File, build.Executable, ExternalProgram],
- T.List[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]],
+ args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram],
+ T.List[T.Union[str, mesonlib.File, ExternalProgram]]],
kwargs: 'TYPE_kwargs') -> None:
if args[1]:
FeatureNew.single_use('Calling "add_dist_script" with multiple arguments',
'0.49.0', self.interpreter.subproject)
- if isinstance(args[0], mesonlib.File):
- FeatureNew.single_use('Passing file object to script parameter of add_dist_script',
- '0.57.0', self.interpreter.subproject)
if self.interpreter.subproject != '':
FeatureNew.single_use('Calling "add_dist_script" in a subproject',
'0.58.0', self.interpreter.subproject)
- script_args = self._process_script_args('add_dist_script', args[1], allow_built=True)
- script = self._find_source_script(args[0], script_args)
+ script_args = self._process_script_args('add_dist_script', args[1])
+ script = self._find_source_script('add_dist_script', args[0], script_args)
self.build.dist_scripts.append(script)
@noPosargs
diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py
index 0f493f2..c6fcaa0 100644
--- a/mesonbuild/interpreterbase/decorators.py
+++ b/mesonbuild/interpreterbase/decorators.py
@@ -19,6 +19,7 @@ from .exceptions import InterpreterException, InvalidArguments
from .operator import MesonOperator
from ._unholder import _unholder
+from dataclasses import dataclass
from functools import wraps
import abc
import itertools
@@ -99,10 +100,9 @@ def disablerIfNotFound(f: TV_func) -> TV_func:
return ret
return T.cast(TV_func, wrapped)
+@dataclass(repr=False, eq=False)
class permittedKwargs:
-
- def __init__(self, permitted: T.Set[str]):
- self.permitted = permitted # type: T.Set[str]
+ permitted: T.Set[str]
def __call__(self, f: TV_func) -> TV_func:
@wraps(f)
@@ -575,6 +575,7 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
return inner
+# This cannot be a dataclass due to https://github.com/python/mypy/issues/5374
class FeatureCheckBase(metaclass=abc.ABCMeta):
"Base class for feature version checks"
@@ -738,6 +739,7 @@ class FeatureDeprecated(FeatureCheckBase):
mlog.warning(*args, location=self.location)
+# This cannot be a dataclass due to https://github.com/python/mypy/issues/5374
class FeatureCheckKwargsBase(metaclass=abc.ABCMeta):
@property
diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py
index 5491558..c8489da 100644
--- a/mesonbuild/linkers/linkers.py
+++ b/mesonbuild/linkers/linkers.py
@@ -72,7 +72,7 @@ class StaticLinker:
return []
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return ([], set())
@@ -309,7 +309,7 @@ class AIXArLinker(ArLikeLinker):
std_args = ['-csr', '-Xany']
-def prepare_rpaths(raw_rpaths: str, build_dir: str, from_dir: str) -> T.List[str]:
+def prepare_rpaths(raw_rpaths: T.Tuple[str, ...], build_dir: str, from_dir: str) -> T.List[str]:
# The rpaths we write must be relative if they point to the build dir,
# because otherwise they have different length depending on the build
# directory. This breaks reproducible builds.
@@ -518,7 +518,7 @@ class DynamicLinker(metaclass=abc.ABCMeta):
raise MesonException('This linker does not support bitcode bundles')
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return ([], set())
@@ -627,7 +627,7 @@ class GnuLikeDynamicLinkerMixin:
return self._apply_prefix(f'-soname,{prefix}{shlib_name}.{suffix}{sostr}')
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin():
@@ -765,7 +765,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
return args
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not rpath_paths and not install_rpath and not build_rpath:
return ([], set())
@@ -846,7 +846,7 @@ class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna
return []
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return ([], set())
@@ -924,7 +924,7 @@ class Xc16DynamicLinker(DynamicLinker):
return []
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return ([], set())
@@ -967,7 +967,7 @@ class CompCertDynamicLinker(DynamicLinker):
raise MesonException(f'{self.id} does not support shared libraries.')
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return ([], set())
@@ -1065,7 +1065,7 @@ class NAGDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
id = 'nag'
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not rpath_paths and not install_rpath and not build_rpath:
return ([], set())
@@ -1110,7 +1110,7 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
return []
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not env.machines[self.for_machine].is_windows():
return (['-R' + os.path.join(build_dir, p) for p in rpath_paths], set())
@@ -1317,7 +1317,7 @@ class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
return ['-z', 'fatal-warnings']
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
if not rpath_paths and not install_rpath and not build_rpath:
return ([], set())
@@ -1364,7 +1364,7 @@ class AIXDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
return self._apply_prefix(['-berok'])
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
- rpath_paths: str, build_rpath: str,
+ rpath_paths: T.Tuple[str, ...], build_rpath: str,
install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
all_paths = mesonlib.OrderedSet() # type: mesonlib.OrderedSet[str]
# install_rpath first, followed by other paths, and the system path last
diff --git a/mesonbuild/mesondata.py b/mesonbuild/mesondata.py
index 43b7bde..508c041 100644
--- a/mesonbuild/mesondata.py
+++ b/mesonbuild/mesondata.py
@@ -13,382 +13,35 @@
# limitations under the License.
-####
-#### WARNING: This is an automatically generated file! Do not edit!
-#### Generated by tools/gen_data.py
-####
-
-
-# TODO: Remember to remove this also from tools/gen_data.py
-from pathlib import Path
+import importlib.resources
+from pathlib import PurePosixPath, Path
import typing as T
if T.TYPE_CHECKING:
from .environment import Environment
-######################
-# BEGIN Data section #
-######################
-
-file_0_data_preload_cmake = '''\
-if(MESON_PS_LOADED)
- return()
-endif()
-
-set(MESON_PS_LOADED ON)
-
-cmake_policy(PUSH)
-cmake_policy(SET CMP0054 NEW) # https://cmake.org/cmake/help/latest/policy/CMP0054.html
-
-# Dummy macros that have a special meaning in the meson code
-macro(meson_ps_execute_delayed_calls)
-endmacro()
-
-macro(meson_ps_reload_vars)
-endmacro()
-
-macro(meson_ps_disabled_function)
- message(WARNING "The function '${ARGV0}' is disabled in the context of CMake subprojects.\n"
- "This should not be an issue but may lead to compilation errors.")
-endmacro()
-
-# Helper macro to inspect the current CMake state
-macro(meson_ps_inspect_vars)
- set(MESON_PS_CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
- set(MESON_PS_CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
- meson_ps_execute_delayed_calls()
-endmacro()
-
-
-# Override some system functions with custom code and forward the args
-# to the original function
-macro(add_custom_command)
- meson_ps_inspect_vars()
- _add_custom_command(${ARGV})
-endmacro()
-
-macro(add_custom_target)
- meson_ps_inspect_vars()
- _add_custom_target(${ARGV})
-endmacro()
-
-macro(set_property)
- meson_ps_inspect_vars()
- _set_property(${ARGV})
-endmacro()
-
-function(set_source_files_properties)
- set(FILES)
- set(I 0)
- set(PROPERTIES OFF)
-
- while(I LESS ARGC)
- if(NOT PROPERTIES)
- if("${ARGV${I}}" STREQUAL "PROPERTIES")
- set(PROPERTIES ON)
- else()
- list(APPEND FILES "${ARGV${I}}")
- endif()
-
- math(EXPR I "${I} + 1")
- else()
- set(ID_IDX ${I})
- math(EXPR PROP_IDX "${ID_IDX} + 1")
-
- set(ID "${ARGV${ID_IDX}}")
- set(PROP "${ARGV${PROP_IDX}}")
-
- set_property(SOURCE ${FILES} PROPERTY "${ID}" "${PROP}")
- math(EXPR I "${I} + 2")
- endif()
- endwhile()
-endfunction()
-
-# Disable some functions that would mess up the CMake meson integration
-macro(target_precompile_headers)
- meson_ps_disabled_function(target_precompile_headers)
-endmacro()
-
-set(MESON_PS_DELAYED_CALLS add_custom_command;add_custom_target;set_property)
-meson_ps_reload_vars()
-
-cmake_policy(POP)
-'''
-
-file_1_data_CMakeLists_txt = '''\
-# fail noisily if attempt to use this file without setting:
-# cmake_minimum_required(VERSION ${CMAKE_VERSION})
-# project(... LANGUAGES ...)
-
-cmake_policy(SET CMP0000 NEW)
-
-set(PACKAGE_FOUND FALSE)
-set(_packageName "${NAME}")
-string(TOUPPER "${_packageName}" PACKAGE_NAME)
-
-while(TRUE)
- if ("${VERSION}" STREQUAL "")
- find_package("${NAME}" QUIET COMPONENTS ${COMPS})
- else()
- find_package("${NAME}" "${VERSION}" QUIET COMPONENTS ${COMPS})
- endif()
-
- # ARCHS has to be set via the CMD interface
- if(${_packageName}_FOUND OR ${PACKAGE_NAME}_FOUND OR "${ARCHS}" STREQUAL "")
- break()
- endif()
-
- list(GET ARCHS 0 CMAKE_LIBRARY_ARCHITECTURE)
- list(REMOVE_AT ARCHS 0)
-endwhile()
-
-if(${_packageName}_FOUND OR ${PACKAGE_NAME}_FOUND)
- set(PACKAGE_FOUND TRUE)
-
- # Check the following variables:
- # FOO_VERSION
- # Foo_VERSION
- # FOO_VERSION_STRING
- # Foo_VERSION_STRING
- if(NOT DEFINED PACKAGE_VERSION)
- if(DEFINED ${_packageName}_VERSION)
- set(PACKAGE_VERSION "${${_packageName}_VERSION}")
- elseif(DEFINED ${PACKAGE_NAME}_VERSION)
- set(PACKAGE_VERSION "${${PACKAGE_NAME}_VERSION}")
- elseif(DEFINED ${_packageName}_VERSION_STRING)
- set(PACKAGE_VERSION "${${_packageName}_VERSION_STRING}")
- elseif(DEFINED ${PACKAGE_NAME}_VERSION_STRING)
- set(PACKAGE_VERSION "${${PACKAGE_NAME}_VERSION_STRING}")
- endif()
- endif()
-
- # Check the following variables:
- # FOO_LIBRARIES
- # Foo_LIBRARIES
- # FOO_LIBS
- # Foo_LIBS
- set(libs)
- if(DEFINED ${_packageName}_LIBRARIES)
- set(libs ${_packageName}_LIBRARIES)
- elseif(DEFINED ${PACKAGE_NAME}_LIBRARIES)
- set(libs ${PACKAGE_NAME}_LIBRARIES)
- elseif(DEFINED ${_packageName}_LIBS)
- set(libs ${_packageName}_LIBS)
- elseif(DEFINED ${PACKAGE_NAME}_LIBS)
- set(libs ${PACKAGE_NAME}_LIBS)
- endif()
-
- # Check the following variables:
- # FOO_INCLUDE_DIRS
- # Foo_INCLUDE_DIRS
- # FOO_INCLUDES
- # Foo_INCLUDES
- # FOO_INCLUDE_DIR
- # Foo_INCLUDE_DIR
- set(includes)
- if(DEFINED ${_packageName}_INCLUDE_DIRS)
- set(includes ${_packageName}_INCLUDE_DIRS)
- elseif(DEFINED ${PACKAGE_NAME}_INCLUDE_DIRS)
- set(includes ${PACKAGE_NAME}_INCLUDE_DIRS)
- elseif(DEFINED ${_packageName}_INCLUDES)
- set(includes ${_packageName}_INCLUDES)
- elseif(DEFINED ${PACKAGE_NAME}_INCLUDES)
- set(includes ${PACKAGE_NAME}_INCLUDES)
- elseif(DEFINED ${_packageName}_INCLUDE_DIR)
- set(includes ${_packageName}_INCLUDE_DIR)
- elseif(DEFINED ${PACKAGE_NAME}_INCLUDE_DIR)
- set(includes ${PACKAGE_NAME}_INCLUDE_DIR)
- endif()
-
- # Check the following variables:
- # FOO_DEFINITIONS
- # Foo_DEFINITIONS
- set(definitions)
- if(DEFINED ${_packageName}_DEFINITIONS)
- set(definitions ${_packageName}_DEFINITIONS)
- elseif(DEFINED ${PACKAGE_NAME}_DEFINITIONS)
- set(definitions ${PACKAGE_NAME}_DEFINITIONS)
- endif()
-
- set(PACKAGE_INCLUDE_DIRS "${${includes}}")
- set(PACKAGE_DEFINITIONS "${${definitions}}")
- set(PACKAGE_LIBRARIES "${${libs}}")
-endif()
-'''
-
-file_2_data_CMakeListsLLVM_txt = '''\
-cmake_minimum_required(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} )
-
-set(PACKAGE_FOUND FALSE)
-
-while(TRUE)
- find_package(LLVM REQUIRED CONFIG QUIET)
-
- # ARCHS has to be set via the CMD interface
- if(LLVM_FOUND OR "${ARCHS}" STREQUAL "")
- break()
- endif()
-
- list(GET ARCHS 0 CMAKE_LIBRARY_ARCHITECTURE)
- list(REMOVE_AT ARCHS 0)
-endwhile()
-
-if(LLVM_FOUND)
- set(PACKAGE_FOUND TRUE)
-
- foreach(mod IN LISTS LLVM_MESON_MODULES)
- # Reset variables
- set(out_mods)
- set(real_mods)
-
- # Generate a lower and upper case version
- string(TOLOWER "${mod}" mod_L)
- string(TOUPPER "${mod}" mod_U)
-
- # Get the mapped components
- llvm_map_components_to_libnames(out_mods ${mod} ${mod_L} ${mod_U})
- list(SORT out_mods)
- list(REMOVE_DUPLICATES out_mods)
-
- # Make sure that the modules exist
- foreach(i IN LISTS out_mods)
- if(TARGET ${i})
- list(APPEND real_mods ${i})
- endif()
- endforeach()
-
- # Set the output variables
- set(MESON_LLVM_TARGETS_${mod} ${real_mods})
- foreach(i IN LISTS real_mods)
- set(MESON_TARGET_TO_LLVM_${i} ${mod})
- endforeach()
- endforeach()
-
- # Check the following variables:
- # LLVM_PACKAGE_VERSION
- # LLVM_VERSION
- # LLVM_VERSION_STRING
- if(NOT DEFINED PACKAGE_VERSION)
- if(DEFINED LLVM_PACKAGE_VERSION)
- set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
- elseif(DEFINED LLVM_VERSION)
- set(PACKAGE_VERSION "${LLVM_VERSION}")
- elseif(DEFINED LLVM_VERSION_STRING)
- set(PACKAGE_VERSION "${LLVM_VERSION_STRING}")
- endif()
- endif()
-
- # Check the following variables:
- # LLVM_LIBRARIES
- # LLVM_LIBS
- set(libs)
- if(DEFINED LLVM_LIBRARIES)
- set(libs LLVM_LIBRARIES)
- elseif(DEFINED LLVM_LIBS)
- set(libs LLVM_LIBS)
- endif()
-
- # Check the following variables:
- # LLVM_INCLUDE_DIRS
- # LLVM_INCLUDES
- # LLVM_INCLUDE_DIR
- set(includes)
- if(DEFINED LLVM_INCLUDE_DIRS)
- set(includes LLVM_INCLUDE_DIRS)
- elseif(DEFINED LLVM_INCLUDES)
- set(includes LLVM_INCLUDES)
- elseif(DEFINED LLVM_INCLUDE_DIR)
- set(includes LLVM_INCLUDE_DIR)
- endif()
-
- # Check the following variables:
- # LLVM_DEFINITIONS
- set(definitions)
- if(DEFINED LLVM_DEFINITIONS)
- set(definitions LLVM_DEFINITIONS)
- endif()
-
- set(PACKAGE_INCLUDE_DIRS "${${includes}}")
- set(PACKAGE_DEFINITIONS "${${definitions}}")
- set(PACKAGE_LIBRARIES "${${libs}}")
-endif()
-'''
-
-file_3_data_CMakePathInfo_txt = '''\
-cmake_minimum_required(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION})
-
-set(TMP_PATHS_LIST)
-list(APPEND TMP_PATHS_LIST ${CMAKE_PREFIX_PATH})
-list(APPEND TMP_PATHS_LIST ${CMAKE_FRAMEWORK_PATH})
-list(APPEND TMP_PATHS_LIST ${CMAKE_APPBUNDLE_PATH})
-list(APPEND TMP_PATHS_LIST $ENV{CMAKE_PREFIX_PATH})
-list(APPEND TMP_PATHS_LIST $ENV{CMAKE_FRAMEWORK_PATH})
-list(APPEND TMP_PATHS_LIST $ENV{CMAKE_APPBUNDLE_PATH})
-list(APPEND TMP_PATHS_LIST ${CMAKE_SYSTEM_PREFIX_PATH})
-list(APPEND TMP_PATHS_LIST ${CMAKE_SYSTEM_FRAMEWORK_PATH})
-list(APPEND TMP_PATHS_LIST ${CMAKE_SYSTEM_APPBUNDLE_PATH})
-
-set(LIB_ARCH_LIST)
-if(CMAKE_LIBRARY_ARCHITECTURE_REGEX)
- file(GLOB implicit_dirs RELATIVE /lib /lib/*-linux-gnu* )
- foreach(dir ${implicit_dirs})
- if("${dir}" MATCHES "${CMAKE_LIBRARY_ARCHITECTURE_REGEX}")
- list(APPEND LIB_ARCH_LIST "${dir}")
- endif()
- endforeach()
-endif()
-
-# "Export" these variables:
-set(MESON_ARCH_LIST ${LIB_ARCH_LIST})
-set(MESON_PATHS_LIST ${TMP_PATHS_LIST})
-set(MESON_CMAKE_ROOT ${CMAKE_ROOT})
-set(MESON_CMAKE_SYSROOT ${CMAKE_SYSROOT})
-set(MESON_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH})
-
-message(STATUS ${TMP_PATHS_LIST})
-'''
-
-
-####################
-# END Data section #
-####################
-
class DataFile:
- def __init__(self, path: Path, sha256sum: str, data: str) -> None:
- self.path = path
- self.sha256sum = sha256sum
- self.data = data
+ def __init__(self, path: str) -> None:
+ self.path = PurePosixPath(path)
def write_once(self, path: Path) -> None:
if not path.exists():
- path.write_text(self.data, encoding='utf-8')
+ data = importlib.resources.read_text( # [ignore encoding] it's on the next lines, Mr. Lint
+ ('mesonbuild' / self.path.parent).as_posix().replace('/', '.'),
+ self.path.name,
+ encoding='utf-8')
+ path.write_text(data, encoding='utf-8')
def write_to_private(self, env: 'Environment') -> Path:
+ try:
+ resource = importlib.resources.files('mesonbuild') / self.path
+ if isinstance(resource, Path):
+ return resource
+ except AttributeError:
+ # fall through to python 3.7 compatible code
+ pass
+
out_file = Path(env.scratch_dir) / 'data' / self.path.name
out_file.parent.mkdir(exist_ok=True)
self.write_once(out_file)
return out_file
-
-
-mesondata = {
- 'cmake/data/preload.cmake': DataFile(
- Path('cmake/data/preload.cmake'),
- 'ce8f30159aab25b92c26c58a219a427d47838bfa0739475221d6c8993b4946e5',
- file_0_data_preload_cmake,
- ),
- 'dependencies/data/CMakeLists.txt': DataFile(
- Path('dependencies/data/CMakeLists.txt'),
- '4dca24afa13e9311f0598a6ac29690490819bd7d82cfdaa0a2fe5eea3c0fa0d5',
- file_1_data_CMakeLists_txt,
- ),
- 'dependencies/data/CMakeListsLLVM.txt': DataFile(
- Path('dependencies/data/CMakeListsLLVM.txt'),
- '412cec3315597041a978d018cdaca282dcd47693793540da88ae2f80d0cbd7cd',
- file_2_data_CMakeListsLLVM_txt,
- ),
- 'dependencies/data/CMakePathInfo.txt': DataFile(
- Path('dependencies/data/CMakePathInfo.txt'),
- '90da8b443982d9c87139b7dc84228eb58cab4315764949637208f25e2bda7db2',
- file_3_data_CMakePathInfo_txt,
- ),
-}
diff --git a/mesonbuild/mesonlib/universal.py b/mesonbuild/mesonlib/universal.py
index f193889..1e3f54e 100644
--- a/mesonbuild/mesonlib/universal.py
+++ b/mesonbuild/mesonlib/universal.py
@@ -425,7 +425,7 @@ class File(HoldableObject):
def suffix(self) -> str:
return os.path.splitext(self.fname)[1][1:].lower()
- def endswith(self, ending: str) -> bool:
+ def endswith(self, ending: T.Union[str, T.Tuple[str, ...]]) -> bool:
return self.fname.endswith(ending)
def split(self, s: str, maxsplit: int = -1) -> T.List[str]:
@@ -1319,11 +1319,11 @@ def extract_as_list(dict_object: T.Dict[_T, _U], key: _T, pop: bool = False) ->
'''
Extracts all values from given dict_object and listifies them.
'''
- fetch = dict_object.get
+ fetch: T.Callable[[_T], _U] = dict_object.get
if pop:
fetch = dict_object.pop
# If there's only one key, we don't return a list with one element
- return listify(fetch(key, []), flatten=True)
+ return listify(fetch(key) or [], flatten=True)
def typeslistify(item: 'T.Union[_T, T.Sequence[_T]]',
@@ -1708,9 +1708,7 @@ class OrderedSet(T.MutableSet[_T]):
insertion.
"""
def __init__(self, iterable: T.Optional[T.Iterable[_T]] = None):
- # typing.OrderedDict is new in 3.7.2, so we can't use that, but we can
- # use MutableMapping, which is fine in this case.
- self.__container = collections.OrderedDict() # type: T.MutableMapping[_T, None]
+ self.__container: T.OrderedDict[_T, None] = collections.OrderedDict()
if iterable:
self.update(iterable)
@@ -1741,12 +1739,10 @@ class OrderedSet(T.MutableSet[_T]):
del self.__container[value]
def move_to_end(self, value: _T, last: bool = True) -> None:
- # Mypy does not know about move_to_end, because it is not part of MutableMapping
- self.__container.move_to_end(value, last) # type: ignore
+ self.__container.move_to_end(value, last)
def pop(self, last: bool = True) -> _T:
- # Mypy does not know about the last argument, because it is not part of MutableMapping
- item, _ = self.__container.popitem(last) # type: ignore
+ item, _ = self.__container.popitem(last)
return item
def update(self, iterable: T.Iterable[_T]) -> None:
@@ -1756,6 +1752,10 @@ class OrderedSet(T.MutableSet[_T]):
def difference(self, set_: T.Union[T.Set[_T], 'OrderedSet[_T]']) -> 'OrderedSet[_T]':
return type(self)(e for e in self if e not in set_)
+ def difference_update(self, iterable: T.Iterable[_T]) -> None:
+ for item in iterable:
+ self.discard(item)
+
def relpath(path: str, start: str) -> str:
# On Windows a relative path can't be evaluated for paths on two different
# drives (i.e. c:\foo and f:\bar). The only thing left to do is to use the
diff --git a/mesonbuild/mesonlib/vsenv.py b/mesonbuild/mesonlib/vsenv.py
index 2ba2b90..fcb0c42 100644
--- a/mesonbuild/mesonlib/vsenv.py
+++ b/mesonbuild/mesonlib/vsenv.py
@@ -26,15 +26,16 @@ def _setup_vsenv(force: bool) -> bool:
return False
if os.environ.get('OSTYPE') == 'cygwin':
return False
- if 'Visual Studio' in os.environ['PATH']:
- return False
- # VSINSTALL is set when running setvars from a Visual Studio installation
- # Tested with Visual Studio 2012 and 2017
- if 'VSINSTALLDIR' in os.environ:
- return False
- # Check explicitly for cl when on Windows
- if shutil.which('cl.exe'):
- return False
+ if 'MESON_FORCE_VSENV_FOR_UNITTEST' not in os.environ:
+ if 'Visual Studio' in os.environ['PATH']:
+ return False
+ # VSINSTALL is set when running setvars from a Visual Studio installation
+ # Tested with Visual Studio 2012 and 2017
+ if 'VSINSTALLDIR' in os.environ:
+ return False
+ # Check explicitly for cl when on Windows
+ if shutil.which('cl.exe'):
+ return False
if not force:
if shutil.which('cc'):
return False
@@ -56,6 +57,7 @@ def _setup_vsenv(force: bool) -> bool:
'-prerelease',
'-requiresAny',
'-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
+ '-requires', 'Microsoft.VisualStudio.Workload.WDExpress',
'-products', '*',
'-utf8',
'-format',
@@ -71,6 +73,9 @@ def _setup_vsenv(force: bool) -> bool:
bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsx86_arm64.bat'
else:
bat_path = bat_root / 'VC/Auxiliary/Build/vcvars64.bat'
+ # if VS is not found try VS Express
+ if not bat_path.exists():
+ bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsx86_amd64.bat'
if not bat_path.exists():
raise MesonException(f'Could not find {bat_path}')
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 06f589b..4d873e5 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -117,6 +117,7 @@ class CommandLineParser:
return 0
def run(self, args):
+ pending_python_deprecation_notice = False
# If first arg is not a known command, assume user wants to run the setup
# command.
known_commands = list(self.commands.keys()) + ['-h', '--help']
@@ -130,10 +131,20 @@ class CommandLineParser:
args = args[1:]
else:
parser = self.parser
+ command = None
args = mesonlib.expand_arguments(args)
options = parser.parse_args(args)
+ if command is None:
+ command = options.command
+
+ # Bump the version here in order to add a pre-exit warning that we are phasing out
+ # support for old python. If this is already the oldest supported version, then
+ # this can never be true and does nothing.
+ if command in ('setup', 'compile', 'test', 'install') and sys.version_info < (3, 7):
+ pending_python_deprecation_notice = True
+
try:
return options.run_func(options)
except MesonException as e:
@@ -156,6 +167,9 @@ class CommandLineParser:
mlog.exception(e)
return 2
finally:
+ if pending_python_deprecation_notice:
+ mlog.notice('You are using Python 3.6 which is EOL. Starting with v0.62.0, '
+ 'Meson will require Python 3.7 or newer', fatal=False)
mlog.shutdown()
def run_script_command(script_name, script_args):
@@ -193,8 +207,8 @@ def ensure_stdout_accepts_unicode():
sys.stdout.buffer = sys.stdout.raw if hasattr(sys.stdout, 'raw') else sys.stdout
def run(original_args, mainfile):
- if sys.version_info < (3, 6):
- print('Meson works correctly only with python 3.6+.')
+ if sys.version_info < (3, 7):
+ print('Meson works correctly only with python 3.7+.')
print(f'You have python {sys.version}.')
print('Please update your environment')
return 1
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index af847f7..47ebb75 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -25,6 +25,7 @@ import subprocess
import sys
import typing as T
+from . import build
from . import environment
from .backend.backends import (
InstallData, InstallDataBase, InstallEmptyDir, InstallSymlinkData,
@@ -32,7 +33,7 @@ from .backend.backends import (
)
from .coredata import major_versions_differ, MesonVersionMismatchException
from .coredata import version as coredata_version
-from .mesonlib import Popen_safe, RealPathAction, is_windows
+from .mesonlib import Popen_safe, RealPathAction, is_windows, setup_vsenv
from .scripts import depfixer, destdir_join
from .scripts.meson_exe import run_exe
try:
@@ -793,6 +794,8 @@ def run(opts: 'ArgumentType') -> int:
if not os.path.exists(os.path.join(opts.wd, datafilename)):
sys.exit('Install data not found. Run this command in build directory root.')
if not opts.no_rebuild:
+ b = build.load(opts.wd)
+ setup_vsenv(b.need_vsenv)
if not rebuild_all(opts.wd):
sys.exit(-1)
os.chdir(opts.wd)
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index 60bc09e..bdc9da5 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -206,7 +206,7 @@ def process_markup(args: T.Sequence[TV_Loggable], keep: bool) -> T.List[str]:
arr.append(str(arg))
return arr
-def force_print(*args: str, nested: str, **kwargs: T.Any) -> None:
+def force_print(*args: str, nested: bool, **kwargs: T.Any) -> None:
if log_disable_stdout:
return
iostr = io.StringIO()
diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py
index 7eab2cb..8fe61c6 100644
--- a/mesonbuild/modules/__init__.py
+++ b/mesonbuild/modules/__init__.py
@@ -80,8 +80,8 @@ class ModuleState:
def find_program(self, prog: T.Union[str, T.List[str]], required: bool = True,
version_func: T.Optional[T.Callable[['ExternalProgram'], str]] = None,
- wanted: T.Optional[str] = None) -> 'ExternalProgram':
- return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, wanted=wanted)
+ wanted: T.Optional[str] = None, silent: bool = False) -> 'ExternalProgram':
+ return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, wanted=wanted, silent=silent)
def test(self, args: T.Tuple[str, T.Union[build.Executable, build.Jar, 'ExternalProgram', mesonlib.File]],
workdir: T.Optional[str] = None,
@@ -91,8 +91,11 @@ class ModuleState:
'env': env,
'depends': depends,
}
+ # typed_* takes a list, and gives a tuple to func_test. Violating that constraint
+ # makes the universe (or at least use of this function) implode
+ real_args = list(args)
# TODO: Use interpreter internal API, but we need to go through @typed_kwargs
- self._interpreter.func_test(self.current_node, args, kwargs)
+ self._interpreter.func_test(self.current_node, real_args, kwargs)
def get_option(self, name: str, subproject: str = '',
machine: MachineChoice = MachineChoice.HOST,
diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py
index 67fdd0c..0f325f5 100644
--- a/mesonbuild/modules/cmake.py
+++ b/mesonbuild/modules/cmake.py
@@ -20,7 +20,7 @@ from . import ExtensionModule, ModuleReturnValue, ModuleObject
from .. import build, mesonlib, mlog, dependencies
from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args
-from ..interpreter import ConfigurationDataObject, SubprojectHolder
+from ..interpreter import SubprojectHolder
from ..interpreterbase import (
FeatureNew,
FeatureNewKwargs,
@@ -34,7 +34,6 @@ from ..interpreterbase import (
InvalidArguments,
InterpreterException,
)
-from ..programs import ExternalProgram
COMPATIBILITIES = ['AnyNewerVersion', 'SameMajorVersion', 'SameMinorVersion', 'ExactVersion']
@@ -213,6 +212,7 @@ class CmakeModule(ExtensionModule):
cmake_detected = False
cmake_root = None
+ @FeatureNew('CMake Module', '0.50.0')
def __init__(self, interpreter):
super().__init__(interpreter)
self.methods.update({
@@ -233,11 +233,11 @@ class CmakeModule(ExtensionModule):
return compiler.sizeof('void *', '', env)
- def detect_cmake(self):
+ def detect_cmake(self, state):
if self.cmake_detected:
return True
- cmakebin = ExternalProgram('cmake', silent=False)
+ cmakebin = state.find_program('cmake', silent=False)
if not cmakebin.found():
return False
@@ -272,7 +272,7 @@ class CmakeModule(ExtensionModule):
if compatibility not in COMPATIBILITIES:
raise mesonlib.MesonException('compatibility must be either AnyNewerVersion, SameMajorVersion or ExactVersion.')
- if not self.detect_cmake():
+ if not self.detect_cmake(state):
raise mesonlib.MesonException('Unable to find cmake')
pkgroot = pkgroot_name = kwargs.get('install_dir', None)
@@ -358,7 +358,7 @@ class CmakeModule(ExtensionModule):
if 'configuration' not in kwargs:
raise mesonlib.MesonException('"configuration" not specified.')
conf = kwargs['configuration']
- if not isinstance(conf, ConfigurationDataObject):
+ if not isinstance(conf, build.ConfigurationData):
raise mesonlib.MesonException('Argument "configuration" is not of type configuration_data')
prefix = state.environment.coredata.get_option(mesonlib.OptionKey('prefix'))
@@ -372,8 +372,8 @@ class CmakeModule(ExtensionModule):
extra = PACKAGE_INIT_EXT.replace('@absInstallDir@', abs_install_dir)
extra = extra.replace('@installPrefix@', prefix)
- self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf.conf_data)
- conf.mark_used()
+ self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf)
+ conf.used = True
conffile = os.path.normpath(inputfile.relative_name())
if conffile not in self.interpreter.build_def_files:
diff --git a/mesonbuild/modules/dlang.py b/mesonbuild/modules/dlang.py
index 60d2885..558ca81 100644
--- a/mesonbuild/modules/dlang.py
+++ b/mesonbuild/modules/dlang.py
@@ -21,20 +21,21 @@ import os
from . import ExtensionModule
from .. import dependencies
from .. import mlog
+from ..interpreterbase import FeatureNew
from ..mesonlib import Popen_safe, MesonException
-from ..programs import ExternalProgram
class DlangModule(ExtensionModule):
class_dubbin = None
init_dub = False
+ @FeatureNew('Dlang Module', '0.48.0')
def __init__(self, interpreter):
super().__init__(interpreter)
self.methods.update({
'generate_dub_file': self.generate_dub_file,
})
- def _init_dub(self):
+ def _init_dub(self, state):
if DlangModule.class_dubbin is None:
self.dubbin = dependencies.DubDependency.class_dubbin
DlangModule.class_dubbin = self.dubbin
@@ -42,7 +43,7 @@ class DlangModule(ExtensionModule):
self.dubbin = DlangModule.class_dubbin
if DlangModule.class_dubbin is None:
- self.dubbin = self.check_dub()
+ self.dubbin = self.check_dub(state)
DlangModule.class_dubbin = self.dubbin
else:
self.dubbin = DlangModule.class_dubbin
@@ -53,7 +54,7 @@ class DlangModule(ExtensionModule):
def generate_dub_file(self, state, args, kwargs):
if not DlangModule.init_dub:
- self._init_dub()
+ self._init_dub(state)
if len(args) < 2:
raise MesonException('Missing arguments')
@@ -109,8 +110,8 @@ class DlangModule(ExtensionModule):
p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2]
return p.returncode, out.strip()
- def check_dub(self):
- dubbin = ExternalProgram('dub', silent=True)
+ def check_dub(self, state):
+ dubbin = state.find_program('dub', silent=True)
if dubbin.found():
try:
p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2]
diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py
index ab3aae2..5faee83 100644
--- a/mesonbuild/modules/fs.py
+++ b/mesonbuild/modules/fs.py
@@ -41,6 +41,7 @@ if T.TYPE_CHECKING:
class FSModule(ExtensionModule):
+ @FeatureNew('Fs Module', '0.53.0')
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__(interpreter)
self.methods.update({
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 326f56b..8e8349b 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -16,6 +16,7 @@
functionality such as gobject-introspection, gresources and gtk-doc'''
import copy
+import itertools
import functools
import os
import subprocess
@@ -29,16 +30,17 @@ from .. import build
from .. import interpreter
from .. import mesonlib
from .. import mlog
-from ..build import CustomTarget, CustomTargetIndex, GeneratedList, InvalidArguments
+from ..build import BuildTarget, CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments
from ..dependencies import Dependency, PkgConfigDependency, InternalDependency
from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, INSTALL_KW, NoneType, in_set_validator
-from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, FeatureNew, FeatureDeprecated
+from ..interpreterbase import noPosargs, noKwargs, FeatureNew, FeatureDeprecated
from ..interpreterbase import typed_kwargs, KwargInfo, ContainerTypeInfo
from ..interpreterbase.decorators import typed_pos_args
from ..mesonlib import (
MachineChoice, MesonException, OrderedSet, Popen_safe, join_args,
)
from ..programs import ExternalProgram, OverrideProgram, EmptyExternalProgram
+from ..scripts.gettext import read_linguas
if T.TYPE_CHECKING:
from typing_extensions import Literal, TypedDict
@@ -118,9 +120,9 @@ if T.TYPE_CHECKING:
install_dir: T.List[str]
check: bool
install: bool
- gobject_typesfile: T.List[str]
- html_assets: T.List[str]
- expand_content_files: T.List[str]
+ gobject_typesfile: T.List[FileOrString]
+ html_assets: T.List[FileOrString]
+ expand_content_files: T.List[FileOrString]
c_args: T.List[str]
include_directories: T.List[T.Union[str, build.IncludeDirs]]
dependencies: T.List[T.Union[Dependency, build.SharedLibrary, build.StaticLibrary]]
@@ -133,7 +135,7 @@ if T.TYPE_CHECKING:
namespace: T.Optional[str]
object_manager: bool
build_by_default: bool
- annotations: T.List[str]
+ annotations: T.List[T.List[str]]
install_header: bool
install_dir: T.Optional[str]
docbook: T.Optional[str]
@@ -152,7 +154,7 @@ if T.TYPE_CHECKING:
nostdinc: bool
prefix: T.Optional[str]
skip_source: bool
- sources: T.List[str]
+ sources: T.List[FileOrString]
stdinc: bool
valist_marshallers: bool
@@ -166,6 +168,36 @@ if T.TYPE_CHECKING:
gir_dirs: T.List[str]
packages: T.List[T.Union[str, InternalDependency]]
+ class _MkEnumsCommon(TypedDict):
+
+ sources: T.List[T.Union[FileOrString, build.GeneratedTypes]]
+ install_header: bool
+ install_dir: T.Optional[str]
+ identifier_prefix: T.Optional[str]
+ symbol_prefix: T.Optional[str]
+
+ class MkEnumsSimple(_MkEnumsCommon):
+
+ header_prefix: str
+ decorator: str
+ function_prefix: str
+ body_prefix: str
+
+ class MkEnums(_MkEnumsCommon):
+
+ c_template: T.Optional[FileOrString]
+ h_template: T.Optional[FileOrString]
+ comments: T.Optional[str]
+ eprod: T.Optional[str]
+ fhead: T.Optional[str]
+ fprod: T.Optional[str]
+ ftail: T.Optional[str]
+ vhead: T.Optional[str]
+ vprod: T.Optional[str]
+ vtail: T.Optional[str]
+ depends: T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]]
+
+
# Differs from the CustomTarget version in that it straight defaults to True
_BUILD_BY_DEFAULT: KwargInfo[bool] = KwargInfo(
'build_by_default', bool, default=True,
@@ -178,6 +210,40 @@ _EXTRA_ARGS_KW: KwargInfo[T.List[str]] = KwargInfo(
listify=True,
)
+_MK_ENUMS_COMMON_KWS: T.List[KwargInfo] = [
+ INSTALL_KW.evolve(name='install_header'),
+ KwargInfo(
+ 'sources',
+ ContainerTypeInfo(list, (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)),
+ listify=True,
+ required=True,
+ ),
+ KwargInfo('install_dir', (str, NoneType)),
+ KwargInfo('identifier_prefix', (str, NoneType)),
+ KwargInfo('symbol_prefix', (str, NoneType)),
+]
+
+def annotations_validator(annotations: T.List[T.Union[str, T.List[str]]]) -> T.Optional[str]:
+
+ """Validate gdbus-codegen annotations argument"""
+
+ badlist = 'must be made up of 3 strings for ELEMENT, KEY, and VALUE'
+
+ if all(isinstance(annot, str) for annot in annotations):
+ if len(annotations) == 3:
+ return None
+ else:
+ return badlist
+ elif not all(isinstance(annot, list) for annot in annotations):
+ for c, annot in enumerate(annotations):
+ if not isinstance(annot, list):
+ return f'element {c+1} must be a list'
+ else:
+ for c, annot in enumerate(annotations):
+ if len(annot) != 3 or not all(isinstance(i, str) for i in annot):
+ return f'element {c+1} {badlist}'
+ return None
+
# gresource compilation is broken due to the way
# the resource compiler and Ninja clash about it
#
@@ -190,12 +256,14 @@ native_glib_version = None
class GnomeModule(ExtensionModule):
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__(interpreter)
- self.gir_dep = None
+ self.gir_dep: T.Optional[Dependency] = None
+ self.giscanner: T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]] = None
+ self.gicompiler: T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]] = None
self.install_glib_compile_schemas = False
- self.install_gio_querymodules = []
+ self.install_gio_querymodules: T.List[str] = []
self.install_gtk_update_icon_cache = False
self.install_update_desktop_database = False
- self.devenv = None
+ self.devenv: T.Optional[build.EnvironmentVariables] = None
self.methods.update({
'post_install': self.post_install,
'compile_resources': self.compile_resources,
@@ -243,7 +311,10 @@ class GnomeModule(ExtensionModule):
def _get_dep(self, state: 'ModuleState', depname: str, native: bool = False,
required: bool = True) -> Dependency:
kwargs = {'native': native, 'required': required}
- return self.interpreter.func_dependency(state.current_node, [depname], kwargs)
+ # FIXME: Even if we fix the function, mypy still can't figure out what's
+ # going on here. And we really dont want to call interpreter
+ # implementations of meson functions anyway.
+ return self.interpreter.func_dependency(state.current_node, [depname], kwargs) # type: ignore
def _get_native_binary(self, state: 'ModuleState', name: str, depname: str,
varname: str, required: bool = True) -> T.Union[ExternalProgram, OverrideProgram, 'build.Executable']:
@@ -260,7 +331,7 @@ class GnomeModule(ExtensionModule):
# Check if pkgconfig has a variable
dep = self._get_dep(state, depname, native=True, required=False)
if dep.found() and dep.type_name == 'pkgconfig':
- value = dep.get_pkgconfig_variable(varname, {})
+ value = dep.get_pkgconfig_variable(varname, [], None)
if value:
return ExternalProgram(name, [value])
@@ -450,8 +521,9 @@ class GnomeModule(ExtensionModule):
rv = [target_c, target_h]
return ModuleReturnValue(rv, rv)
+ @staticmethod
def _get_gresource_dependencies(
- self, state: 'ModuleState', input_file: str, source_dirs: T.List[str],
+ state: 'ModuleState', input_file: str, source_dirs: T.List[str],
dependencies: T.Sequence[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]
) -> T.Tuple[T.List[mesonlib.FileOrString], T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]], T.List[str]]:
@@ -525,17 +597,19 @@ class GnomeModule(ExtensionModule):
def _get_link_args(self, state: 'ModuleState',
lib: T.Union[build.SharedLibrary, build.StaticLibrary],
- depends: T.List[build.BuildTarget],
+ depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString']],
include_rpath: bool = False,
- use_gir_args: bool = False) -> T.List[str]:
+ use_gir_args: bool = False
+ ) -> T.Tuple[T.List[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString']]]:
link_command: T.List[str] = []
+ new_depends = list(depends)
# Construct link args
if isinstance(lib, build.SharedLibrary):
libdir = os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(lib))
link_command.append('-L' + libdir)
if include_rpath:
link_command.append('-Wl,-rpath,' + libdir)
- depends.append(lib)
+ new_depends.append(lib)
# Needed for the following binutils bug:
# https://github.com/mesonbuild/meson/issues/1911
# However, g-ir-scanner does not understand -Wl,-rpath
@@ -549,13 +623,17 @@ class GnomeModule(ExtensionModule):
link_command.append('--extra-library=' + lib.name)
else:
link_command.append('-l' + lib.name)
- return link_command
+ return link_command, new_depends
def _get_dependencies_flags(
- self, deps: T.Sequence[T.Union['Dependency', build.SharedLibrary, build.StaticLibrary]],
- state: 'ModuleState', depends: T.List[build.BuildTarget], include_rpath: bool = False,
- use_gir_args: bool = False, separate_nodedup: bool = False
- ) -> T.Tuple[OrderedSet[str], OrderedSet[str], OrderedSet[str], T.Optional[T.List[str]], OrderedSet[str]]:
+ self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]],
+ state: 'ModuleState',
+ depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString']],
+ include_rpath: bool = False,
+ use_gir_args: bool = False,
+ separate_nodedup: bool = False
+ ) -> T.Tuple[OrderedSet[str], OrderedSet[str], OrderedSet[str], T.Optional[T.List[str]], OrderedSet[str],
+ T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString']]]:
cflags: OrderedSet[str] = OrderedSet()
internal_ldflags: OrderedSet[str] = OrderedSet()
external_ldflags: OrderedSet[str] = OrderedSet()
@@ -564,6 +642,7 @@ class GnomeModule(ExtensionModule):
external_ldflags_nodedup: T.List[str] = []
gi_includes: OrderedSet[str] = OrderedSet()
deps = mesonlib.listify(deps)
+ depends = list(depends)
for dep in deps:
if isinstance(dep, Dependency):
@@ -576,7 +655,8 @@ class GnomeModule(ExtensionModule):
cflags.update(state.get_include_args(dep.include_directories))
for lib in dep.libraries:
if isinstance(lib, build.SharedLibrary):
- internal_ldflags.update(self._get_link_args(state, lib, depends, include_rpath))
+ _ld, depends = self._get_link_args(state, lib, depends, include_rpath)
+ internal_ldflags.update(_ld)
libdepflags = self._get_dependencies_flags(lib.get_external_deps(), state, depends, include_rpath,
use_gir_args, True)
cflags.update(libdepflags[0])
@@ -640,9 +720,9 @@ class GnomeModule(ExtensionModule):
external_ldflags = fix_ldflags(external_ldflags)
if not separate_nodedup:
external_ldflags.update(external_ldflags_nodedup)
- return cflags, internal_ldflags, external_ldflags, None, gi_includes
+ return cflags, internal_ldflags, external_ldflags, None, gi_includes, depends
else:
- return cflags, internal_ldflags, external_ldflags, external_ldflags_nodedup, gi_includes
+ return cflags, internal_ldflags, external_ldflags, external_ldflags_nodedup, gi_includes, depends
def _unwrap_gir_target(self, girtarget: T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState'
) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary]:
@@ -684,7 +764,8 @@ class GnomeModule(ExtensionModule):
return p.returncode == 0 and option in o
# May mutate depends and gir_inc_dirs
- def _scan_include(self, state: 'ModuleState', includes: T.List[T.Union[str, GirTarget]]
+ @staticmethod
+ def _scan_include(state: 'ModuleState', includes: T.List[T.Union[str, GirTarget]]
) -> T.Tuple[T.List[str], T.List[str], T.List[GirTarget]]:
ret: T.List[str] = []
gir_inc_dirs: T.List[str] = []
@@ -700,7 +781,8 @@ class GnomeModule(ExtensionModule):
return ret, gir_inc_dirs, depends
- def _scan_langs(self, state: 'ModuleState', langs: T.Iterable[str]) -> T.List[str]:
+ @staticmethod
+ def _scan_langs(state: 'ModuleState', langs: T.Iterable[str]) -> T.List[str]:
ret: T.List[str] = []
for lang in langs:
@@ -711,7 +793,8 @@ class GnomeModule(ExtensionModule):
return ret
- def _scan_gir_targets(self, state: 'ModuleState', girtargets: T.List[build.BuildTarget]) -> T.List[T.Union[str, build.Executable]]:
+ @staticmethod
+ def _scan_gir_targets(state: 'ModuleState', girtargets: T.Sequence[build.BuildTarget]) -> T.List[T.Union[str, build.Executable]]:
ret: T.List[T.Union[str, build.Executable]] = []
for girtarget in girtargets:
@@ -744,7 +827,8 @@ class GnomeModule(ExtensionModule):
return ret
- def _get_girtargets_langs_compilers(self, girtargets: T.Sequence[build.BuildTarget]) -> T.List[T.Tuple[str, 'Compiler']]:
+ @staticmethod
+ def _get_girtargets_langs_compilers(girtargets: T.Sequence[build.BuildTarget]) -> T.List[T.Tuple[str, 'Compiler']]:
ret: T.List[T.Tuple[str, 'Compiler']] = []
for girtarget in girtargets:
for lang, compiler in girtarget.compilers.items():
@@ -755,21 +839,24 @@ class GnomeModule(ExtensionModule):
return ret
- def _get_gir_targets_deps(self, girtargets: T.Sequence[build.BuildTarget]
- ) -> T.List[T.Union[build.Target, Dependency]]:
- ret: T.List[T.Union[build.Target, Dependency]] = []
+ @staticmethod
+ def _get_gir_targets_deps(girtargets: T.Sequence[build.BuildTarget]
+ ) -> T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, Dependency]]:
+ ret: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, Dependency]] = []
for girtarget in girtargets:
ret += girtarget.get_all_link_deps()
ret += girtarget.get_external_deps()
return ret
- def _get_gir_targets_inc_dirs(self, girtargets: T.List[build.BuildTarget]) -> T.List[build.IncludeDirs]:
+ @staticmethod
+ def _get_gir_targets_inc_dirs(girtargets: T.Sequence[build.BuildTarget]) -> T.List[build.IncludeDirs]:
ret: T.List[build.IncludeDirs] = []
for girtarget in girtargets:
ret += girtarget.get_include_dirs()
return ret
- def _get_langs_compilers_flags(self, state: 'ModuleState', langs_compilers: T.List[T.Tuple[str, 'Compiler']]
+ @staticmethod
+ def _get_langs_compilers_flags(state: 'ModuleState', langs_compilers: T.List[T.Tuple[str, 'Compiler']]
) -> T.Tuple[T.List[str], T.List[str], T.List[str]]:
cflags: T.List[str] = []
internal_ldflags: T.List[str] = []
@@ -797,8 +884,9 @@ class GnomeModule(ExtensionModule):
return cflags, internal_ldflags, external_ldflags
- def _make_gir_filelist(self, state: 'ModuleState', srcdir: str, ns: str,
- nsversion: str, girtargets: T.List[build.BuildTarget],
+ @staticmethod
+ def _make_gir_filelist(state: 'ModuleState', srcdir: str, ns: str,
+ nsversion: str, girtargets: T.Sequence[build.BuildTarget],
libsources: T.Sequence[T.Union[
str, mesonlib.File, build.GeneratedList,
build.CustomTarget, build.CustomTargetIndex]]
@@ -825,9 +913,14 @@ class GnomeModule(ExtensionModule):
return gir_filelist_filename
- def _make_gir_target(self, state: 'ModuleState', girfile: str, scan_command: T.List[str],
- generated_files: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]],
- depends: T.List[build.Target], kwargs: T.Dict[str, T.Any]) -> GirTarget:
+ @staticmethod
+ def _make_gir_target(
+ state: 'ModuleState',
+ girfile: str,
+ scan_command: T.Sequence[T.Union['FileOrString', Executable, ExternalProgram, OverrideProgram]],
+ generated_files: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]],
+ depends: T.Sequence[T.Union['FileOrString', build.BuildTarget, 'build.GeneratedTypes']],
+ kwargs: T.Dict[str, T.Any]) -> GirTarget:
install = kwargs['install_gir']
if install is None:
install = kwargs['install']
@@ -851,7 +944,9 @@ class GnomeModule(ExtensionModule):
return GirTarget(girfile, state.subdir, state.subproject, scankwargs)
- def _make_typelib_target(self, state: 'ModuleState', typelib_output: str, typelib_cmd: T.List[str],
+ @staticmethod
+ def _make_typelib_target(state: 'ModuleState', typelib_output: str,
+ typelib_cmd: T.Sequence[T.Union[str, build.Executable, ExternalProgram, build.CustomTarget]],
generated_files: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]],
kwargs: T.Dict[str, T.Any]) -> TypelibTarget:
install = kwargs['install_typelib']
@@ -867,7 +962,7 @@ class GnomeModule(ExtensionModule):
typelib_kwargs = {
'input': generated_files,
'output': [typelib_output],
- 'command': typelib_cmd,
+ 'command': list(typelib_cmd),
'install': install,
'install_dir': install_dir,
'install_tag': 'typelib',
@@ -876,19 +971,24 @@ class GnomeModule(ExtensionModule):
return TypelibTarget(typelib_output, state.subdir, state.subproject, typelib_kwargs)
- # May mutate depends
- def _gather_typelib_includes_and_update_depends(self, state: 'ModuleState', deps: T.List[Dependency], depends: T.List[build.Target]) -> T.List[str]:
+ @staticmethod
+ def _gather_typelib_includes_and_update_depends(
+ state: 'ModuleState',
+ deps: T.Sequence[T.Union[Dependency, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]],
+ depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString']]
+ ) -> T.Tuple[T.List[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString']]]:
# Need to recursively add deps on GirTarget sources from our
# dependencies and also find the include directories needed for the
# typelib generation custom target below.
typelib_includes: T.List[str] = []
+ new_depends = list(depends)
for dep in deps:
# Add a dependency on each GirTarget listed in dependencies and add
# the directory where it will be generated to the typelib includes
if isinstance(dep, InternalDependency):
for source in dep.sources:
if isinstance(source, GirTarget) and source not in depends:
- depends.append(source)
+ new_depends.append(source)
subdir = os.path.join(state.environment.get_build_dir(),
source.get_subdir())
if subdir not in typelib_includes:
@@ -899,10 +999,10 @@ class GnomeModule(ExtensionModule):
# FIXME: Store this in the original form from declare_dependency()
# so it can be used here directly.
elif isinstance(dep, build.SharedLibrary):
- for source in dep.generated:
- if isinstance(source, GirTarget):
+ for g_source in dep.generated:
+ if isinstance(g_source, GirTarget):
subdir = os.path.join(state.environment.get_build_dir(),
- source.get_subdir())
+ g_source.get_subdir())
if subdir not in typelib_includes:
typelib_includes.append(subdir)
if isinstance(dep, Dependency):
@@ -910,9 +1010,10 @@ class GnomeModule(ExtensionModule):
assert isinstance(girdir, str), 'for mypy'
if girdir and girdir not in typelib_includes:
typelib_includes.append(girdir)
- return typelib_includes
+ return typelib_includes, new_depends
- def _get_external_args_for_langs(self, state: 'ModuleState', langs: T.Sequence[str]) -> T.List[str]:
+ @staticmethod
+ def _get_external_args_for_langs(state: 'ModuleState', langs: T.Sequence[str]) -> T.List[str]:
ret: T.List[str] = []
for lang in langs:
ret += mesonlib.listify(state.environment.coredata.get_external_args(MachineChoice.HOST, lang))
@@ -977,7 +1078,7 @@ class GnomeModule(ExtensionModule):
srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
- depends: T.List[T.Union['FileOrString', build.GeneratedTypes, build.Executable, build.SharedLibrary, build.StaticLibrary]] = []
+ depends: T.List[T.Union['FileOrString', 'build.GeneratedTypes', build.BuildTarget]] = []
depends.extend(gir_dep.sources)
depends.extend(girtargets)
@@ -986,11 +1087,11 @@ class GnomeModule(ExtensionModule):
deps = self._get_gir_targets_deps(girtargets)
deps += kwargs['dependencies']
deps += [gir_dep]
- typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends)
+ typelib_includes, depends = self._gather_typelib_includes_and_update_depends(state, deps, depends)
# ldflags will be misinterpreted by gir scanner (showing
# spurious dependencies) but building GStreamer fails if they
# are not used here.
- dep_cflags, dep_internal_ldflags, dep_external_ldflags, _, gi_includes = \
+ dep_cflags, dep_internal_ldflags, dep_external_ldflags, _, gi_includes, depends = \
self._get_dependencies_flags(deps, state, depends, use_gir_args=True)
scan_cflags = []
scan_cflags += list(self._get_scanner_cflags(cflags))
@@ -1032,7 +1133,7 @@ class GnomeModule(ExtensionModule):
scan_command += scan_cflags
scan_command += ['--cflags-end']
scan_command += state.get_include_args(inc_dirs)
- scan_command += state.get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
+ scan_command += state.get_include_args(itertools.chain(gi_includes, gir_inc_dirs, inc_dirs), prefix='--add-include-path=')
scan_command += list(scan_internal_ldflags)
scan_command += self._scan_gir_targets(state, girtargets)
scan_command += self._scan_langs(state, [lc[0] for lc in langs_compilers])
@@ -1050,7 +1151,10 @@ class GnomeModule(ExtensionModule):
generated_files = [f for f in libsources if isinstance(f, (GeneratedList, CustomTarget, CustomTargetIndex))]
- scan_target = self._make_gir_target(state, girfile, scan_command, generated_files, depends, kwargs)
+ scan_target = self._make_gir_target(
+ state, girfile, scan_command, generated_files, depends,
+ # We have to cast here because mypy can't figure this out
+ T.cast(T.Dict[str, T.Any], kwargs))
typelib_output = f'{ns}-{nsversion}.typelib'
typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@']
@@ -1059,7 +1163,7 @@ class GnomeModule(ExtensionModule):
for incdir in typelib_includes:
typelib_cmd += ["--includedir=" + incdir]
- typelib_target = self._make_typelib_target(state, typelib_output, typelib_cmd, generated_files, kwargs)
+ typelib_target = self._make_typelib_target(state, typelib_output, typelib_cmd, generated_files, T.cast(T.Dict[str, T.Any], kwargs))
self._devenv_prepend('GI_TYPELIB_PATH', os.path.join(state.environment.get_build_dir(), state.subdir))
@@ -1111,47 +1215,102 @@ class GnomeModule(ExtensionModule):
raise MesonException('Yelp requires a list of sources')
elif args[1]:
mlog.warning('"gnome.yelp" ignores positional sources arguments when the "sources" keyword argument is set')
- source_str = '@@'.join(sources)
+ sources_files = [mesonlib.File.from_source_file(state.environment.source_dir,
+ os.path.join(state.subdir, 'C'),
+ s) for s in sources]
langs = kwargs['languages']
+ if not langs:
+ langs = read_linguas(os.path.join(state.environment.source_dir, state.subdir))
+
+ media = kwargs['media']
+ symlinks = kwargs['symlink_media']
+ targets: T.List[T.Union['build.Target', build.Data, build.SymlinkData]] = []
+ potargets: T.List[build.RunTarget] = []
+
+ itstool = state.find_program('itstool')
+ msgmerge = state.find_program('msgmerge')
+ msgfmt = state.find_program('msgfmt')
+
+ install_dir = os.path.join(state.environment.get_datadir(), 'help')
+ c_install_dir = os.path.join(install_dir, 'C', project_id)
+ c_data = build.Data(sources_files, c_install_dir, c_install_dir,
+ mesonlib.FileMode(), state.subproject)
+ targets.append(c_data)
+
+ media_files: T.List[mesonlib.File] = []
+ for m in media:
+ f = mesonlib.File.from_source_file(state.environment.source_dir,
+ os.path.join(state.subdir, 'C'), m)
+ media_files.append(f)
+ m_install_dir = os.path.join(c_install_dir, os.path.dirname(m))
+ m_data = build.Data([f], m_install_dir, m_install_dir,
+ mesonlib.FileMode(), state.subproject)
+ targets.append(m_data)
+
+ pot_file = os.path.join('@SOURCE_ROOT@', state.subdir, 'C', project_id + '.pot')
+ pot_sources = [os.path.join('@SOURCE_ROOT@', state.subdir, 'C', s) for s in sources]
+ pot_args: T.List[T.Union['ExternalProgram', str]] = [itstool, '-o', pot_file]
+ pot_args.extend(pot_sources)
+ pottarget = build.RunTarget(f'help-{project_id}-pot', pot_args, [],
+ os.path.join(state.subdir, 'C'), state.subproject)
+ targets.append(pottarget)
+
+ for l in langs:
+ l_subdir = os.path.join(state.subdir, l)
+ l_install_dir = os.path.join(install_dir, l, project_id)
+
+ for i, m in enumerate(media):
+ m_dir = os.path.dirname(m)
+ m_install_dir = os.path.join(l_install_dir, m_dir)
+ l_data: T.Union[build.Data, build.SymlinkData]
+ if symlinks:
+ link_target = os.path.join(os.path.relpath(c_install_dir, start=m_install_dir), m)
+ l_data = build.SymlinkData(link_target, os.path.basename(m),
+ m_install_dir, state.subproject)
+ else:
+ try:
+ m_file = mesonlib.File.from_source_file(state.environment.source_dir, l_subdir, m)
+ except MesonException:
+ m_file = media_files[i]
+ l_data = build.Data([m_file], m_install_dir, m_install_dir,
+ mesonlib.FileMode(), state.subproject)
+ targets.append(l_data)
+
+ po_file = l + '.po'
+ po_args: T.List[T.Union['ExternalProgram', str]] = [
+ msgmerge, '-q', '-o',
+ os.path.join('@SOURCE_ROOT@', l_subdir, po_file),
+ os.path.join('@SOURCE_ROOT@', l_subdir, po_file), pot_file]
+ potarget = build.RunTarget(f'help-{project_id}-{l}-update-po',
+ po_args, [pottarget], l_subdir, state.subproject)
+ targets.append(potarget)
+ potargets.append(potarget)
+
+ gmo_file = project_id + '-' + l + '.gmo'
+ gmo_kwargs = {'command': [msgfmt, '@INPUT@', '-o', '@OUTPUT@'],
+ 'input': po_file,
+ 'output': gmo_file,
+ }
+ gmotarget = build.CustomTarget(f'help-{project_id}-{l}-gmo', l_subdir, state.subproject, gmo_kwargs)
+ targets.append(gmotarget)
+
+ merge_kwargs = {'command': [itstool, '-m', os.path.join(l_subdir, gmo_file),
+ '-o', '@OUTDIR@', '@INPUT@'],
+ 'input': sources_files,
+ 'output': sources,
+ 'depends': gmotarget,
+ 'install': True,
+ 'install_dir': l_install_dir,
+ }
+ mergetarget = build.CustomTarget(f'help-{project_id}-{l}', l_subdir, state.subproject, merge_kwargs)
+ targets.append(mergetarget)
- script = state.environment.get_build_command()
- inscript_args = ['--internal',
- 'yelphelper',
- 'install',
- '--subdir=' + state.subdir,
- '--id=' + project_id,
- '--installdir=' + os.path.join(state.environment.get_datadir(), 'help'),
- '--sources=' + source_str]
- if kwargs['symlink_media']:
- inscript_args.append('--symlinks=true')
- if kwargs['media']:
- inscript_args.append('--media=' + '@@'.join(kwargs['media']))
- if langs:
- inscript_args.append('--langs=' + '@@'.join(langs))
- inscript = state.backend.get_executable_serialisation(script + inscript_args)
-
- potargs = state.environment.get_build_command() + [
- '--internal', 'yelphelper', 'pot',
- '--subdir=' + state.subdir,
- '--id=' + project_id,
- '--sources=' + source_str,
- ]
- pottarget = build.RunTarget('help-' + project_id + '-pot', potargs,
- [], state.subdir, state.subproject)
-
- poargs = state.environment.get_build_command() + [
- '--internal', 'yelphelper', 'update-po',
- '--subdir=' + state.subdir,
- '--id=' + project_id,
- '--sources=' + source_str,
- '--langs=' + '@@'.join(langs),
- ]
- potarget = build.RunTarget('help-' + project_id + '-update-po', poargs,
- [], state.subdir, state.subproject)
-
- rv: T.List[T.Union[build.ExecutableSerialisation, build.RunTarget]] = [inscript, pottarget, potarget]
- return ModuleReturnValue(None, rv)
+ allpotarget = build.AliasTarget(f'help-{project_id}-update-po', potargets,
+ state.subdir, state.subproject)
+ targets.append(allpotarget)
+
+ return ModuleReturnValue(None, targets)
@typed_pos_args('gnome.gtkdoc', str)
@typed_kwargs(
@@ -1163,11 +1322,11 @@ class GnomeModule(ExtensionModule):
'dependencies',
ContainerTypeInfo(list, (Dependency, build.SharedLibrary, build.StaticLibrary)),
listify=True, default=[]),
- KwargInfo('expand_content_files', ContainerTypeInfo(list, str), default=[], listify=True),
+ KwargInfo('expand_content_files', ContainerTypeInfo(list, (str, mesonlib.File)), default=[], listify=True),
KwargInfo('fixxref_args', ContainerTypeInfo(list, str), default=[], listify=True),
- KwargInfo('gobject_typesfile', ContainerTypeInfo(list, str), default=[], listify=True),
+ KwargInfo('gobject_typesfile', ContainerTypeInfo(list, (str, mesonlib.File)), default=[], listify=True),
KwargInfo('html_args', ContainerTypeInfo(list, str), default=[], listify=True),
- KwargInfo('html_assets', ContainerTypeInfo(list, str), default=[], listify=True),
+ KwargInfo('html_assets', ContainerTypeInfo(list, (str, mesonlib.File)), default=[], listify=True),
KwargInfo('ignore_headers', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo(
'include_directories',
@@ -1193,7 +1352,7 @@ class GnomeModule(ExtensionModule):
main_xml = kwargs['main_xml']
if main_xml is not None:
if main_file is not None:
- raise InvalidArguments('gnome.gtkdoc: main_xml and main_xgml are exclusive arguments')
+ raise InvalidArguments('gnome.gtkdoc: main_xml and main_sgml are exclusive arguments')
main_file = main_xml
moduleversion = kwargs['module_version']
targetname = modulename + ('-' + moduleversion if moduleversion else '') + '-doc'
@@ -1293,7 +1452,8 @@ class GnomeModule(ExtensionModule):
def _get_build_args(self, c_args: T.List[str], inc_dirs: T.List[T.Union[str, build.IncludeDirs]],
deps: T.List[T.Union[Dependency, build.SharedLibrary, build.StaticLibrary]],
- state: 'ModuleState', depends: T.List[build.BuildTarget]) -> T.List[str]:
+ state: 'ModuleState',
+ depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes']]) -> T.List[str]:
args: T.List[str] = []
cflags = c_args.copy()
deps_cflags, internal_ldflags, external_ldflags, *_ = \
@@ -1328,7 +1488,7 @@ class GnomeModule(ExtensionModule):
def gtkdoc_html_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> str:
return os.path.join('share/gtk-doc/html', args[0])
- @typed_pos_args('gnome.gdbus_codegen', str, optargs=[str])
+ @typed_pos_args('gnome.gdbus_codegen', str, optargs=[(str, mesonlib.File)])
@typed_kwargs(
'gnome.gdbus_codegen',
_BUILD_BY_DEFAULT.evolve(since='0.40.0'),
@@ -1338,10 +1498,10 @@ class GnomeModule(ExtensionModule):
KwargInfo('namespace', (str, NoneType)),
KwargInfo('object_manager', bool, default=False),
KwargInfo(
- 'annotations', ContainerTypeInfo(list, str),
- listify=True,
+ 'annotations', ContainerTypeInfo(list, (list, str)),
default=[],
- validator=lambda x: 'must be made up of 3 strings for ELEMENT, KEY, and VALUE' if len(x) != 3 else None
+ validator=annotations_validator,
+ convertor=lambda x: [x] if x and isinstance(x[0], str) else x,
),
KwargInfo('install_header', bool, default=False, since='0.46.0'),
KwargInfo('install_dir', (str, NoneType), since='0.46.0'),
@@ -1350,7 +1510,7 @@ class GnomeModule(ExtensionModule):
'autocleanup', str, default='default', since='0.47.0',
validator=in_set_validator({'all', 'none', 'objects'})),
)
- def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[str]],
+ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional['FileOrString']],
kwargs: 'GdbusCodegen') -> ModuleReturnValue:
namebase = args[0]
xml_files: T.List['FileOrString'] = [args[1]] if args[1] else []
@@ -1381,9 +1541,9 @@ class GnomeModule(ExtensionModule):
build_by_default = kwargs['build_by_default']
# Annotations are a bit ugly in that they are a list of lists of strings...
- if kwargs['annotations']:
+ for annot in kwargs['annotations']:
cmd.append('--annotate')
- cmd.extend(kwargs['annotations'])
+ cmd.extend(annot)
targets = []
install_header = kwargs['install_header']
@@ -1475,80 +1635,54 @@ class GnomeModule(ExtensionModule):
return ModuleReturnValue(targets, targets)
- @permittedKwargs({'sources', 'c_template', 'h_template', 'install_header', 'install_dir',
- 'comments', 'identifier_prefix', 'symbol_prefix', 'eprod', 'vprod',
- 'fhead', 'fprod', 'ftail', 'vhead', 'vtail', 'depends'})
@typed_pos_args('gnome.mkenums', str)
- def mkenums(self, state: 'ModuleState', args: T.Tuple[str], kwargs) -> ModuleReturnValue:
+ @typed_kwargs(
+ 'gnome.mkenums',
+ *_MK_ENUMS_COMMON_KWS,
+ DEPENDS_KW,
+ KwargInfo('c_template', (str, mesonlib.File, NoneType)),
+ KwargInfo('h_template', (str, mesonlib.File, NoneType)),
+ KwargInfo('comments', (str, NoneType)),
+ KwargInfo('eprod', (str, NoneType)),
+ KwargInfo('fhead', (str, NoneType)),
+ KwargInfo('fprod', (str, NoneType)),
+ KwargInfo('ftail', (str, NoneType)),
+ KwargInfo('vhead', (str, NoneType)),
+ KwargInfo('vprod', (str, NoneType)),
+ KwargInfo('vtail', (str, NoneType)),
+ )
+ def mkenums(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEnums') -> ModuleReturnValue:
basename = args[0]
- if 'sources' not in kwargs:
- raise MesonException('Missing keyword argument "sources".')
- sources = kwargs.pop('sources')
- if isinstance(sources, str):
- sources = [sources]
- elif not isinstance(sources, list):
- raise MesonException(
- 'Sources keyword argument must be a string or array.')
+ c_template = kwargs['c_template']
+ if isinstance(c_template, mesonlib.File):
+ c_template = c_template.absolute_path(state.environment.source_dir, state.environment.build_dir)
+ h_template = kwargs['h_template']
+ if isinstance(h_template, mesonlib.File):
+ h_template = h_template.absolute_path(state.environment.source_dir, state.environment.build_dir)
- cmd = []
+ cmd: T.List[str] = []
known_kwargs = ['comments', 'eprod', 'fhead', 'fprod', 'ftail',
- 'identifier_prefix', 'symbol_prefix', 'template',
+ 'identifier_prefix', 'symbol_prefix',
'vhead', 'vprod', 'vtail']
- known_custom_target_kwargs = ['install_dir', 'build_always',
- 'depends', 'depend_files']
- c_template = h_template = None
- install_header = False
- for arg, value in kwargs.items():
- if arg == 'sources':
- raise AssertionError("sources should've already been handled")
- elif arg == 'c_template':
- c_template = value
- if isinstance(c_template, mesonlib.File):
- c_template = c_template.absolute_path(state.environment.source_dir, state.environment.build_dir)
- if 'template' in kwargs:
- raise MesonException('Mkenums does not accept both '
- 'c_template and template keyword '
- 'arguments at the same time.')
- elif arg == 'h_template':
- h_template = value
- if isinstance(h_template, mesonlib.File):
- h_template = h_template.absolute_path(state.environment.source_dir, state.environment.build_dir)
- if 'template' in kwargs:
- raise MesonException('Mkenums does not accept both '
- 'h_template and template keyword '
- 'arguments at the same time.')
- elif arg == 'install_header':
- install_header = value
- elif arg in known_kwargs:
- cmd += ['--' + arg.replace('_', '-'), value]
- elif arg not in known_custom_target_kwargs:
- raise MesonException(
- f'Mkenums does not take a {arg} keyword argument.')
- cmd = [state.find_program(['glib-mkenums', 'mkenums'])] + cmd
- custom_kwargs = {}
- for arg in known_custom_target_kwargs:
- if arg in kwargs:
- custom_kwargs[arg] = kwargs[arg]
+ for arg in known_kwargs:
+ # mypy can't figure this out
+ if kwargs[arg]: # type: ignore
+ cmd += ['--' + arg.replace('_', '-'), kwargs[arg]] # type: ignore
- targets = []
+ targets: T.List[CustomTarget] = []
+ h_target: T.Optional[CustomTarget] = None
if h_template is not None:
h_output = os.path.basename(os.path.splitext(h_template)[0])
# We always set template as the first element in the source array
# so --template consumes it.
h_cmd = cmd + ['--template', '@INPUT@']
- h_sources = [h_template] + sources
-
- # Copy so we don't mutate the arguments for the c_template
- h_kwargs = custom_kwargs.copy()
- h_kwargs['install'] = install_header
- if 'install_dir' not in h_kwargs:
- h_kwargs['install_dir'] = \
- state.environment.coredata.get_option(mesonlib.OptionKey('includedir'))
- h_target = self._make_mkenum_custom_target(state, h_sources,
- h_output, h_cmd,
- h_kwargs)
+ h_sources: T.List[T.Union[FileOrString, 'build.GeneratedTypes']] = [h_template]
+ h_sources.extend(kwargs['sources'])
+ h_target = self._make_mkenum_impl(
+ state, h_sources, h_output, h_cmd, install=kwargs['install_header'],
+ install_dir=kwargs['install_dir'])
targets.append(h_target)
if c_template is not None:
@@ -1556,110 +1690,86 @@ class GnomeModule(ExtensionModule):
# We always set template as the first element in the source array
# so --template consumes it.
c_cmd = cmd + ['--template', '@INPUT@']
- c_sources = [c_template] + sources
-
- c_kwargs = custom_kwargs.copy()
- # Never install the C file. Complain on bug tracker if you need it.
- c_kwargs['install'] = False
- c_kwargs['install_dir'] = []
- if h_template is not None:
- if 'depends' in custom_kwargs:
- c_kwargs['depends'] += [h_target]
- else:
- c_kwargs['depends'] = h_target
- c_target = self._make_mkenum_custom_target(state, c_sources,
- c_output, c_cmd,
- c_kwargs)
+ c_sources: T.List[T.Union[FileOrString, 'build.GeneratedTypes']] = [c_template]
+ c_sources.extend(kwargs['sources'])
+
+ depends = kwargs['depends'].copy()
+ if h_target is not None:
+ depends.append(h_target)
+ c_target = self._make_mkenum_impl(
+ state, c_sources, c_output, c_cmd, depends=depends)
targets.insert(0, c_target)
if c_template is None and h_template is None:
generic_cmd = cmd + ['@INPUT@']
- custom_kwargs['install'] = install_header
- if 'install_dir' not in custom_kwargs:
- custom_kwargs['install_dir'] = \
- state.environment.coredata.get_option(mesonlib.OptionKey('includedir'))
- target = self._make_mkenum_custom_target(state, sources, basename,
- generic_cmd, custom_kwargs)
+ target = self._make_mkenum_impl(
+ state, kwargs['sources'], basename, generic_cmd,
+ install=kwargs['install_header'],
+ install_dir=kwargs['install_dir'])
return ModuleReturnValue(target, [target])
- elif len(targets) == 1:
- return ModuleReturnValue(targets[0], [targets[0]])
else:
return ModuleReturnValue(targets, targets)
@FeatureNew('gnome.mkenums_simple', '0.42.0')
@typed_pos_args('gnome.mkenums_simple', str)
- def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs) -> ModuleReturnValue:
+ @typed_kwargs(
+ 'gnome.mkenums_simple',
+ *_MK_ENUMS_COMMON_KWS,
+ KwargInfo('header_prefix', str, default=''),
+ KwargInfo('function_prefix', str, default=''),
+ KwargInfo('body_prefix', str, default=''),
+ KwargInfo('decorator', str, default=''),
+ )
+ def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEnumsSimple') -> ModuleReturnValue:
hdr_filename = f'{args[0]}.h'
body_filename = f'{args[0]}.c'
- # not really needed, just for sanity checking
- forbidden_kwargs = ['c_template', 'h_template', 'eprod', 'fhead',
- 'fprod', 'ftail', 'vhead', 'vtail', 'comments']
- for arg in forbidden_kwargs:
- if arg in kwargs:
- raise MesonException(f'mkenums_simple() does not take a {arg} keyword argument')
-
- # kwargs to pass as-is from mkenums_simple() to mkenums()
- shared_kwargs = ['sources', 'install_header', 'install_dir',
- 'identifier_prefix', 'symbol_prefix']
- mkenums_kwargs = {}
- for arg in shared_kwargs:
- if arg in kwargs:
- mkenums_kwargs[arg] = kwargs[arg]
-
- # .c file generation
- c_file_kwargs = copy.deepcopy(mkenums_kwargs)
- if 'sources' not in kwargs:
- raise MesonException('Missing keyword argument "sources".')
- sources = kwargs['sources']
- if isinstance(sources, str):
- sources = [sources]
- elif not isinstance(sources, list):
- raise MesonException(
- 'Sources keyword argument must be a string or array.')
-
- # The `install_header` argument will be used by mkenums() when
- # not using template files, so we need to forcibly unset it
- # when generating the C source file, otherwise we will end up
- # installing it
- c_file_kwargs['install_header'] = False
-
- header_prefix = kwargs.get('header_prefix', '')
- decl_decorator = kwargs.get('decorator', '')
- func_prefix = kwargs.get('function_prefix', '')
- body_prefix = kwargs.get('body_prefix', '')
+ header_prefix = kwargs['header_prefix']
+ decl_decorator = kwargs['decorator']
+ func_prefix = kwargs['function_prefix']
+ body_prefix = kwargs['body_prefix']
+ cmd: T.List[str] = []
+ if kwargs['identifier_prefix']:
+ cmd.extend(['--identifier-prefix', kwargs['identifier_prefix']])
+ if kwargs['symbol_prefix']:
+ cmd.extend(['--symbol-prefix', kwargs['symbol_prefix']])
+
+ c_cmd = cmd.copy()
# Maybe we should write our own template files into the build dir
# instead, but that seems like much more work, nice as it would be.
fhead = ''
if body_prefix != '':
fhead += '%s\n' % body_prefix
fhead += '#include "%s"\n' % hdr_filename
- for hdr in sources:
+ for hdr in kwargs['sources']:
fhead += '#include "{}"\n'.format(os.path.basename(str(hdr)))
fhead += textwrap.dedent(
'''
#define C_ENUM(v) ((gint) v)
#define C_FLAGS(v) ((guint) v)
''')
- c_file_kwargs['fhead'] = fhead
+ c_cmd.extend(['--fhead', fhead])
- c_file_kwargs['fprod'] = textwrap.dedent(
+ c_cmd.append('--fprod')
+ c_cmd.append(textwrap.dedent(
'''
/* enumerations from "@basename@" */
- ''')
+ '''))
- c_file_kwargs['vhead'] = textwrap.dedent(
+ c_cmd.append('--vhead')
+ c_cmd.append(textwrap.dedent(
f'''
GType
{func_prefix}@enum_name@_get_type (void)
{{
static gsize gtype_id = 0;
- static const G@Type@Value values[] = {{''')
+ static const G@Type@Value values[] = {{'''))
- c_file_kwargs['vprod'] = ' { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },'
+ c_cmd.extend(['--vprod', ' { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },'])
- c_file_kwargs['vtail'] = textwrap.dedent(
+ c_cmd.append('--vtail')
+ c_cmd.append(textwrap.dedent(
''' { 0, NULL, NULL }
};
if (g_once_init_enter (&gtype_id)) {
@@ -1667,55 +1777,72 @@ class GnomeModule(ExtensionModule):
g_once_init_leave (&gtype_id, new_type);
}
return (GType) gtype_id;
- }''')
+ }'''))
+ c_cmd.append('@INPUT@')
- rv = self.mkenums(state, [body_filename], c_file_kwargs)
- c_file = rv.return_value
+ c_file = self._make_mkenum_impl(state, kwargs['sources'], body_filename, c_cmd)
# .h file generation
- h_file_kwargs = copy.deepcopy(mkenums_kwargs)
+ h_cmd = cmd.copy()
- h_file_kwargs['fhead'] = textwrap.dedent(
+ h_cmd.append('--fhead')
+ h_cmd.append(textwrap.dedent(
f'''#pragma once
#include <glib-object.h>
{header_prefix}
G_BEGIN_DECLS
- ''')
+ '''))
- h_file_kwargs['fprod'] = textwrap.dedent(
+ h_cmd.append('--fprod')
+ h_cmd.append(textwrap.dedent(
'''
/* enumerations from "@basename@" */
- ''')
+ '''))
- h_file_kwargs['vhead'] = textwrap.dedent(
+ h_cmd.append('--vhead')
+ h_cmd.append(textwrap.dedent(
f'''
{decl_decorator}
GType {func_prefix}@enum_name@_get_type (void);
- #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ ({func_prefix}@enum_name@_get_type())''')
+ #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ ({func_prefix}@enum_name@_get_type())'''))
- h_file_kwargs['ftail'] = textwrap.dedent(
+ h_cmd.append('--ftail')
+ h_cmd.append(textwrap.dedent(
'''
- G_END_DECLS''')
+ G_END_DECLS'''))
+ h_cmd.append('@INPUT@')
- rv = self.mkenums(state, [hdr_filename], h_file_kwargs)
- h_file = rv.return_value
+ h_file = self._make_mkenum_impl(
+ state, kwargs['sources'], hdr_filename, h_cmd,
+ install=kwargs['install_header'],
+ install_dir=kwargs['install_dir'])
return ModuleReturnValue([c_file, h_file], [c_file, h_file])
@staticmethod
- def _make_mkenum_custom_target(
+ def _make_mkenum_impl(
state: 'ModuleState',
sources: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]],
- output: str, cmd: T.List[str], kwargs: T.Dict[str, T.Any]) -> build.CustomTarget:
+ output: str,
+ cmd: T.List[str],
+ *,
+ install: bool = False,
+ install_dir: T.Optional[T.Sequence[T.Union[str, bool]]] = None,
+ depends: T.Optional[T.Sequence[T.Union[CustomTarget, CustomTargetIndex, BuildTarget]]] = None
+ ) -> build.CustomTarget:
+ real_cmd: T.List[T.Union[str, ExternalProgram]] = [state.find_program(['glib-mkenums', 'mkenums'])]
+ real_cmd.extend(cmd)
custom_kwargs = {
'input': sources,
'output': [output],
'capture': True,
- 'command': cmd
+ 'command': real_cmd,
+ 'install': install,
+ 'install_dir': install_dir or state.environment.coredata.get_option(mesonlib.OptionKey('includedir')),
+ 'depends': list(depends or []),
}
- custom_kwargs.update(kwargs)
return build.CustomTarget(output, state.subdir, state.subproject, custom_kwargs,
# https://github.com/mesonbuild/meson/issues/973
absolute_paths=True)
@@ -1732,7 +1859,7 @@ class GnomeModule(ExtensionModule):
KwargInfo('nostdinc', bool, default=False),
KwargInfo('prefix', (str, NoneType)),
KwargInfo('skip_source', bool, default=False),
- KwargInfo('sources', ContainerTypeInfo(list, str, allow_empty=False), listify=True, required=True),
+ KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File), allow_empty=False), listify=True, required=True),
KwargInfo('stdinc', bool, default=False),
KwargInfo('valist_marshallers', bool, default=False),
)
@@ -1793,7 +1920,7 @@ class GnomeModule(ExtensionModule):
return ModuleReturnValue(rv, rv)
def _extract_vapi_packages(self, state: 'ModuleState', packages: T.List[T.Union[InternalDependency, str]],
- ) -> T.Tuple[T.List[str], T.List[build.Target], T.List[str], T.List[str], T.List[str]]:
+ ) -> T.Tuple[T.List[str], T.List[VapiTarget], T.List[str], T.List[str], T.List[str]]:
'''
Packages are special because we need to:
- Get a list of packages for the .deps file
@@ -1803,7 +1930,7 @@ class GnomeModule(ExtensionModule):
'''
if not packages:
return [], [], [], [], []
- vapi_depends: T.List[build.Target] = []
+ vapi_depends: T.List[VapiTarget] = []
vapi_packages: T.List[str] = []
vapi_includes: T.List[str] = []
vapi_args: T.List[str] = []
@@ -1866,7 +1993,7 @@ class GnomeModule(ExtensionModule):
KwargInfo('packages', ContainerTypeInfo(list, (str, InternalDependency)), listify=True, default=[]),
)
def generate_vapi(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenerateVapi') -> ModuleReturnValue:
- created_values: T.List[Dependency] = []
+ created_values: T.List[T.Union[Dependency, build.Data]] = []
library = args[0]
build_dir = os.path.join(state.environment.get_build_dir(), state.subdir)
source_dir = os.path.join(state.environment.get_source_dir(), state.subdir)
@@ -1874,7 +2001,7 @@ class GnomeModule(ExtensionModule):
cmd: T.List[T.Union[str, 'ExternalProgram']]
cmd = [state.find_program('vapigen'), '--quiet', f'--library={library}', f'--directory={build_dir}']
cmd.extend([f'--vapidir={d}' for d in kwargs['vapi_dirs']])
- cmd.extend([f'--metadatdir={d}' for d in kwargs['metadata_dirs']])
+ cmd.extend([f'--metadatadir={d}' for d in kwargs['metadata_dirs']])
cmd.extend([f'--girdir={d}' for d in kwargs['gir_dirs']])
cmd += pkg_cmd
cmd += ['--metadatadir=' + source_dir]
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 4a0b39e..6c5d347 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -183,7 +183,8 @@ class DependenciesHelper:
# lists in case a library is link_with and link_whole at the same time.
# See remove_dups() below.
self.link_whole_targets.append(t)
- self._add_lib_dependencies(t.link_targets, t.link_whole_targets, t.external_deps, public)
+ if isinstance(t, build.BuildTarget):
+ self._add_lib_dependencies(t.link_targets, t.link_whole_targets, t.external_deps, public)
def add_version_reqs(self, name, version_reqs):
if version_reqs:
diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py
index 90335a1..2b62ea3 100644
--- a/mesonbuild/modules/python.py
+++ b/mesonbuild/modules/python.py
@@ -79,10 +79,19 @@ class _PythonDependencyBase(_Base):
class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase):
def __init__(self, name: str, environment: 'Environment',
- kwargs: T.Dict[str, T.Any], installation: 'PythonInstallation'):
+ kwargs: T.Dict[str, T.Any], installation: 'PythonInstallation',
+ libpc: bool = False):
+ if libpc:
+ mlog.debug(f'Searching for {name!r} via pkgconfig lookup in LIBPC')
+ else:
+ mlog.debug(f'Searching for {name!r} via fallback pkgconfig lookup in default paths')
+
PkgConfigDependency.__init__(self, name, environment, kwargs)
_PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
+ if libpc and not self.is_found:
+ mlog.debug(f'"python-{self.version}" could not be found in LIBPC, this is likely due to a relocated python installation')
+
class PythonFrameworkDependency(ExtraFrameworkDependency, _PythonDependencyBase):
@@ -240,12 +249,15 @@ def python_factory(env: 'Environment', for_machine: 'MachineChoice',
# If python-X.Y.pc exists in LIBPC, we will try to use it
def wrap_in_pythons_pc_dir(name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
installation: 'PythonInstallation') -> 'ExternalDependency':
+ if not pkg_libdir:
+ # there is no LIBPC, so we can't search in it
+ return NotFoundDependency('python', env)
+
old_pkg_libdir = os.environ.pop('PKG_CONFIG_LIBDIR', None)
old_pkg_path = os.environ.pop('PKG_CONFIG_PATH', None)
- if pkg_libdir:
- os.environ['PKG_CONFIG_LIBDIR'] = pkg_libdir
+ os.environ['PKG_CONFIG_LIBDIR'] = pkg_libdir
try:
- return PythonPkgConfigDependency(name, env, kwargs, installation)
+ return PythonPkgConfigDependency(name, env, kwargs, installation, True)
finally:
def set_env(name, value):
if value is not None:
@@ -255,10 +267,11 @@ def python_factory(env: 'Environment', for_machine: 'MachineChoice',
set_env('PKG_CONFIG_LIBDIR', old_pkg_libdir)
set_env('PKG_CONFIG_PATH', old_pkg_path)
- candidates.extend([
- functools.partial(wrap_in_pythons_pc_dir, pkg_name, env, kwargs, installation),
- functools.partial(PythonPkgConfigDependency, pkg_name, env, kwargs, installation)
- ])
+ candidates.append(functools.partial(wrap_in_pythons_pc_dir, pkg_name, env, kwargs, installation))
+ # We only need to check both, if a python install has a LIBPC. It might point to the wrong location,
+ # e.g. relocated / cross compilation, but the presence of LIBPC indicates we should definitely look for something.
+ if pkg_libdir is not None:
+ candidates.append(functools.partial(PythonPkgConfigDependency, pkg_name, env, kwargs, installation))
if DependencyMethods.SYSTEM in methods:
candidates.append(functools.partial(PythonSystemDependency, 'python', env, kwargs, installation))
diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py
index dc1f7c7..f7600e2 100644
--- a/mesonbuild/modules/python3.py
+++ b/mesonbuild/modules/python3.py
@@ -16,12 +16,13 @@ import sysconfig
from .. import mesonlib
from . import ExtensionModule
-from ..interpreterbase import noKwargs, permittedKwargs, FeatureDeprecated
+from ..interpreterbase import noKwargs, permittedKwargs, FeatureDeprecated, FeatureNew
from ..build import known_shmod_kwargs
from ..programs import ExternalProgram
class Python3Module(ExtensionModule):
+ @FeatureNew('python3 module', '0.38.0')
@FeatureDeprecated('python3 module', '0.48.0')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
diff --git a/mesonbuild/modules/qt6.py b/mesonbuild/modules/qt6.py
index d9cd651..3cfe243 100644
--- a/mesonbuild/modules/qt6.py
+++ b/mesonbuild/modules/qt6.py
@@ -13,10 +13,12 @@
# limitations under the License.
from .qt import QtBaseModule
+from ..interpreterbase import FeatureNew
class Qt6Module(QtBaseModule):
+ @FeatureNew('Qt6 Module', '0.57.0')
def __init__(self, interpreter):
QtBaseModule.__init__(self, interpreter, qt_version=6)
diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py
deleted file mode 100644
index 1fae144..0000000
--- a/mesonbuild/modules/rpm.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright 2015 The Meson development team
-
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-'''This module provides helper functions for RPM related
-functionality such as generating template RPM spec file.'''
-
-from .. import build
-from .. import compilers
-import datetime
-from .. import mlog
-from . import GirTarget, TypelibTarget
-from . import ExtensionModule
-from ..interpreterbase import noKwargs
-
-import os
-
-class RPMModule(ExtensionModule):
- def __init__(self, interpreter):
- super().__init__(interpreter)
- self.methods.update({
- 'generate_spec_template': self.generate_spec_template,
- })
-
- @noKwargs
- def generate_spec_template(self, state, args, kwargs):
- required_compilers = self.__get_required_compilers(state)
- proj = state.project_name.replace(' ', '_').replace('\t', '_')
- so_installed = False
- devel_subpkg = False
- files = set()
- files_devel = set()
- to_delete = set()
- for target in state.targets.values():
- if isinstance(target, build.Executable) and target.need_install:
- files.add('%%{_bindir}/%s' % target.get_filename())
- elif isinstance(target, build.SharedLibrary) and target.need_install:
- files.add('%%{_libdir}/%s' % target.get_filename())
- for alias in target.get_aliases():
- if alias.endswith('.so'):
- files_devel.add('%%{_libdir}/%s' % alias)
- else:
- files.add('%%{_libdir}/%s' % alias)
- so_installed = True
- elif isinstance(target, build.StaticLibrary) and target.need_install:
- to_delete.add('%%{buildroot}%%{_libdir}/%s' % target.get_filename())
- mlog.warning('removing', mlog.bold(target.get_filename()),
- 'from package because packaging static libs not recommended')
- elif isinstance(target, GirTarget) and target.should_install():
- files_devel.add('%%{_datadir}/gir-1.0/%s' % target.get_filename()[0])
- elif isinstance(target, TypelibTarget) and target.should_install():
- files.add('%%{_libdir}/girepository-1.0/%s' % target.get_filename()[0])
- for header in state.headers:
- if header.get_install_subdir():
- files_devel.add('%%{_includedir}/%s/' % header.get_install_subdir())
- else:
- for hdr_src in header.get_sources():
- files_devel.add('%%{_includedir}/%s' % hdr_src)
- for man in state.man:
- for man_file in man.get_sources():
- if man.locale:
- files.add('%%{_mandir}/%s/man%u/%s.*' % (man.locale, int(man_file.split('.')[-1]), man_file))
- else:
- files.add('%%{_mandir}/man%u/%s.*' % (int(man_file.split('.')[-1]), man_file))
- if files_devel:
- devel_subpkg = True
-
- filename = os.path.join(state.environment.get_build_dir(),
- '%s.spec' % proj)
- with open(filename, 'w+', encoding='utf-8') as fn:
- fn.write('Name: %s\n' % proj)
- fn.write('Version: # FIXME\n')
- fn.write('Release: 1%{?dist}\n')
- fn.write('Summary: # FIXME\n')
- fn.write('License: # FIXME\n')
- fn.write('\n')
- fn.write('Source0: %{name}-%{version}.tar.xz # FIXME\n')
- fn.write('\n')
- fn.write('BuildRequires: meson\n')
- for compiler in required_compilers:
- fn.write('BuildRequires: %s\n' % compiler)
- for dep in state.environment.coredata.deps.host:
- fn.write('BuildRequires: pkgconfig(%s)\n' % dep[0])
-# ext_libs and ext_progs have been removed from coredata so the following code
-# no longer works. It is kept as a reminder of the idea should anyone wish
-# to re-implement it.
-#
-# for lib in state.environment.coredata.ext_libs.values():
-# name = lib.get_name()
-# fn.write('BuildRequires: {} # FIXME\n'.format(name))
-# mlog.warning('replace', mlog.bold(name), 'with the real package.',
-# 'You can use following command to find package which '
-# 'contains this lib:',
-# mlog.bold("dnf provides '*/lib{}.so'".format(name)))
-# for prog in state.environment.coredata.ext_progs.values():
-# if not prog.found():
-# fn.write('BuildRequires: %%{_bindir}/%s # FIXME\n' %
-# prog.get_name())
-# else:
-# fn.write('BuildRequires: {}\n'.format(prog.get_path()))
- fn.write('\n')
- fn.write('%description\n')
- fn.write('\n')
- if devel_subpkg:
- fn.write('%package devel\n')
- fn.write('Summary: Development files for %{name}\n')
- fn.write('Requires: %{name}%{?_isa} = %{?epoch:%{epoch}:}{version}-%{release}\n')
- fn.write('\n')
- fn.write('%description devel\n')
- fn.write('Development files for %{name}.\n')
- fn.write('\n')
- fn.write('%prep\n')
- fn.write('%autosetup\n')
- fn.write('\n')
- fn.write('%build\n')
- fn.write('%meson\n')
- fn.write('%meson_build\n')
- fn.write('\n')
- fn.write('%install\n')
- fn.write('%meson_install\n')
- if to_delete:
- fn.write('rm -vf %s\n' % ' '.join(to_delete))
- fn.write('\n')
- fn.write('%check\n')
- fn.write('%meson_test\n')
- fn.write('\n')
- fn.write('%files\n')
- for f in files:
- fn.write('%s\n' % f)
- fn.write('\n')
- if devel_subpkg:
- fn.write('%files devel\n')
- for f in files_devel:
- fn.write('%s\n' % f)
- fn.write('\n')
- if so_installed:
- fn.write('%post -p /sbin/ldconfig\n')
- fn.write('%postun -p /sbin/ldconfig\n')
- fn.write('\n')
- fn.write('%changelog\n')
- fn.write('* %s meson <meson@example.com> - \n' %
- datetime.date.today().strftime('%a %b %d %Y'))
- fn.write('- \n')
- fn.write('\n')
- mlog.log('RPM spec template written to %s.spec.\n' % proj)
-
- def __get_required_compilers(self, state):
- required_compilers = set()
- for compiler in state.environment.coredata.compilers.host.values():
- # Elbrus has one 'lcc' package for every compiler
- if isinstance(compiler, compilers.GnuCCompiler):
- required_compilers.add('gcc')
- elif isinstance(compiler, compilers.GnuCPPCompiler):
- required_compilers.add('gcc-c++')
- elif isinstance(compiler, compilers.ElbrusCCompiler):
- required_compilers.add('lcc')
- elif isinstance(compiler, compilers.ElbrusCPPCompiler):
- required_compilers.add('lcc')
- elif isinstance(compiler, compilers.ElbrusFortranCompiler):
- required_compilers.add('lcc')
- elif isinstance(compiler, compilers.ValaCompiler):
- required_compilers.add('vala')
- elif isinstance(compiler, compilers.GnuFortranCompiler):
- required_compilers.add('gcc-gfortran')
- elif isinstance(compiler, compilers.GnuObjCCompiler):
- required_compilers.add('gcc-objc')
- elif compiler == compilers.GnuObjCPPCompiler:
- required_compilers.add('gcc-objc++')
- else:
- mlog.log('RPM spec file not created, generation not allowed for:',
- mlog.bold(compiler.get_id()))
- return required_compilers
-
-
-def initialize(*args, **kwargs):
- return RPMModule(*args, **kwargs)
diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py
index ba8b300..515e670 100644
--- a/mesonbuild/modules/sourceset.py
+++ b/mesonbuild/modules/sourceset.py
@@ -154,8 +154,12 @@ class SourceSet(MutableModuleObject):
def _get_from_config_data(key):
nonlocal config_cache
if key not in config_cache:
- args = [key] if strict else [key, False]
- config_cache[key] = config_data.get_method(args, {})
+ if key in config_data:
+ config_cache[key] = config_data.get(key)[0]
+ elif strict:
+ raise InvalidArguments(f'sourceset.apply: key "{key}" not in passed configuration, and strict set.')
+ else:
+ config_cache[key] = False
return config_cache[key]
files = self.collect(_get_from_config_data, False)
diff --git a/mesonbuild/modules/unstable_simd.py b/mesonbuild/modules/unstable_simd.py
index 3339cea..8715a14 100644
--- a/mesonbuild/modules/unstable_simd.py
+++ b/mesonbuild/modules/unstable_simd.py
@@ -13,6 +13,7 @@
# limitations under the License.
from .. import mesonlib, compilers, mlog
+from .. import build
from . import ExtensionModule
@@ -57,8 +58,7 @@ class SimdModule(ExtensionModule):
compiler = kwargs['compiler']
if not isinstance(compiler, compilers.compilers.Compiler):
raise mesonlib.MesonException('Compiler argument must be a compiler object.')
- cdata = self.interpreter.func_configuration_data(None, [], {})
- conf = cdata.conf_data
+ conf = build.ConfigurationData()
for iset in self.isets:
if iset not in kwargs:
continue
@@ -82,7 +82,7 @@ class SimdModule(ExtensionModule):
all_lang_args = old_lang_args + args
lib_kwargs[langarg_key] = all_lang_args
result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs))
- return [result, cdata]
+ return [result, conf]
def initialize(*args, **kwargs):
return SimdModule(*args, **kwargs)
diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py
index c470e29..735766e 100644
--- a/mesonbuild/mparser.py
+++ b/mesonbuild/mparser.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from dataclasses import dataclass
import re
import codecs
import textwrap
@@ -87,15 +88,15 @@ class BlockParseException(MesonException):
TV_TokenTypes = T.TypeVar('TV_TokenTypes', int, str, bool)
+@dataclass(eq=False)
class Token(T.Generic[TV_TokenTypes]):
- def __init__(self, tid: str, filename: str, line_start: int, lineno: int, colno: int, bytespan: T.Tuple[int, int], value: TV_TokenTypes):
- self.tid = tid # type: str
- self.filename = filename # type: str
- self.line_start = line_start # type: int
- self.lineno = lineno # type: int
- self.colno = colno # type: int
- self.bytespan = bytespan # type: T.Tuple[int, int]
- self.value = value # type: TV_TokenTypes
+ tid: str
+ filename: str
+ line_start: int
+ lineno: int
+ colno: int
+ bytespan: T.Tuple[int, int]
+ value: TV_TokenTypes
def __eq__(self, other: object) -> bool:
if isinstance(other, str):
@@ -237,13 +238,19 @@ class Lexer:
if not matched:
raise ParseException('lexer', self.getline(line_start), lineno, col)
+@dataclass(eq=False)
class BaseNode:
- def __init__(self, lineno: int, colno: int, filename: str, end_lineno: T.Optional[int] = None, end_colno: T.Optional[int] = None):
- self.lineno = lineno # type: int
- self.colno = colno # type: int
- self.filename = filename # type: str
- self.end_lineno = end_lineno if end_lineno is not None else self.lineno
- self.end_colno = end_colno if end_colno is not None else self.colno
+ lineno: int
+ colno: int
+ filename: str
+ end_lineno: T.Optional[int] = None
+ end_colno: T.Optional[int] = None
+
+ def __post_init__(self) -> None:
+ if self.end_lineno is None:
+ self.end_lineno = self.lineno
+ if self.end_colno is None:
+ self.end_colno = self.colno
# Attributes for the visitors
self.level = 0 # type: int
diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py
index 67bfca8..4eb3632 100755
--- a/mesonbuild/msubprojects.py
+++ b/mesonbuild/msubprojects.py
@@ -1,3 +1,4 @@
+from dataclasses import dataclass, InitVar
import os, subprocess
import argparse
import asyncio
@@ -94,18 +95,22 @@ class Logger:
self.print_progress()
+@dataclass(eq=False)
class Runner:
- def __init__(self, logger: Logger, r: Resolver, wrap: PackageDefinition, repo_dir: str, options: 'Arguments') -> None:
+ logger: Logger
+ r: InitVar[Resolver]
+ wrap: PackageDefinition
+ repo_dir: str
+ options: 'Arguments'
+
+ def __post_init__(self, r: Resolver) -> None:
# FIXME: Do a copy because Resolver.resolve() is stateful method that
# cannot be called from multiple threads.
self.wrap_resolver = copy.copy(r)
- self.wrap_resolver.dirname = os.path.join(r.subdir_root, wrap.directory)
- self.wrap = self.wrap_resolver.wrap = wrap
- self.repo_dir = repo_dir
- self.options = options
- self.run_method: T.Callable[[], bool] = options.subprojects_func.__get__(self) # type: ignore
+ self.wrap_resolver.dirname = os.path.join(r.subdir_root, self.wrap.directory)
+ self.wrap_resolver.wrap = self.wrap
+ self.run_method: T.Callable[[], bool] = self.options.subprojects_func.__get__(self) # type: ignore
self.log_queue: T.List[T.Tuple[mlog.TV_LoggableList, T.Any]] = []
- self.logger = logger
def log(self, *args: mlog.TV_Loggable, **kwargs: T.Any) -> None:
self.log_queue.append((list(args), kwargs))
diff --git a/mesonbuild/scripts/yelphelper.py b/mesonbuild/scripts/yelphelper.py
deleted file mode 100644
index 374104b..0000000
--- a/mesonbuild/scripts/yelphelper.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Copyright 2016 The Meson development team
-
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import subprocess
-import shutil
-import argparse
-from .. import mlog
-from ..mesonlib import has_path_sep
-from . import destdir_join
-from .gettext import read_linguas
-import typing as T
-
-parser = argparse.ArgumentParser()
-parser.add_argument('command')
-parser.add_argument('--id', dest='project_id')
-parser.add_argument('--subdir', dest='subdir')
-parser.add_argument('--installdir', dest='install_dir')
-parser.add_argument('--sources', dest='sources')
-parser.add_argument('--media', dest='media', default='')
-parser.add_argument('--langs', dest='langs', default='')
-parser.add_argument('--symlinks', type=bool, dest='symlinks', default=False)
-
-def build_pot(srcdir: str, project_id: str, sources: T.List[str]) -> None:
- # Must be relative paths
- sources = [os.path.join('C', source) for source in sources]
- outfile = os.path.join(srcdir, project_id + '.pot')
- subprocess.call(['itstool', '-o', outfile] + sources)
-
-def update_po(srcdir: str, project_id: str, langs: T.List[str]) -> None:
- potfile = os.path.join(srcdir, project_id + '.pot')
- for lang in langs:
- pofile = os.path.join(srcdir, lang, lang + '.po')
- subprocess.call(['msgmerge', '-q', '-o', pofile, pofile, potfile])
-
-def build_translations(srcdir: str, blddir: str, langs: T.List[str]) -> None:
- for lang in langs:
- outdir = os.path.join(blddir, lang)
- os.makedirs(outdir, exist_ok=True)
- subprocess.call([
- 'msgfmt', os.path.join(srcdir, lang, lang + '.po'),
- '-o', os.path.join(outdir, lang + '.gmo')
- ])
-
-def merge_translations(blddir: str, sources: T.List[str], langs: T.List[str]) -> None:
- for lang in langs:
- subprocess.call([
- 'itstool', '-m', os.path.join(blddir, lang, lang + '.gmo'),
- '-o', os.path.join(blddir, lang)
- ] + sources)
-
-def install_help(srcdir: str, blddir: str, sources: T.List[str], media: T.List[str], langs: T.List[str], install_dir: str, destdir: str, project_id: str, symlinks: bool) -> None:
- c_install_dir = os.path.join(install_dir, 'C', project_id)
- for lang in langs + ['C']:
- indir = destdir_join(destdir, os.path.join(install_dir, lang, project_id))
- os.makedirs(indir, exist_ok=True)
- for source in sources:
- infile = os.path.join(srcdir if lang == 'C' else blddir, lang, source)
- outfile = os.path.join(indir, source)
- mlog.log(f'Installing {infile} to {outfile}')
- shutil.copy2(infile, outfile)
- for m in media:
- infile = os.path.join(srcdir, lang, m)
- outfile = os.path.join(indir, m)
- c_infile = os.path.join(srcdir, 'C', m)
- if not os.path.exists(infile):
- if not os.path.exists(c_infile):
- mlog.warning('Media file "%s" did not exist in C directory' % m)
- continue
- elif symlinks:
- srcfile = os.path.join(c_install_dir, m)
- mlog.log(f'Symlinking {outfile} to {srcfile}.')
- if has_path_sep(m):
- os.makedirs(os.path.dirname(outfile), exist_ok=True)
- try:
- try:
- os.symlink(srcfile, outfile)
- except FileExistsError:
- os.remove(outfile)
- os.symlink(srcfile, outfile)
- continue
- except (NotImplementedError, OSError):
- mlog.warning('Symlinking not supported, falling back to copying')
- infile = c_infile
- else:
- # Lang doesn't have media file so copy it over 'C' one
- infile = c_infile
- mlog.log(f'Installing {infile} to {outfile}')
- if has_path_sep(m):
- os.makedirs(os.path.dirname(outfile), exist_ok=True)
- shutil.copyfile(infile, outfile)
- shutil.copystat(infile, outfile)
-
-def run(args: T.List[str]) -> int:
- options = parser.parse_args(args)
- langs = options.langs.split('@@') if options.langs else []
- media = options.media.split('@@') if options.media else []
- sources = options.sources.split('@@')
- destdir = os.environ.get('DESTDIR', '')
- src_subdir = os.path.join(os.environ['MESON_SOURCE_ROOT'], options.subdir)
- build_subdir = os.path.join(os.environ['MESON_BUILD_ROOT'], options.subdir)
- abs_sources = [os.path.join(src_subdir, 'C', source) for source in sources]
-
- if not langs:
- langs = read_linguas(src_subdir)
-
- if options.command == 'pot':
- build_pot(src_subdir, options.project_id, sources)
- elif options.command == 'update-po':
- build_pot(src_subdir, options.project_id, sources)
- update_po(src_subdir, options.project_id, langs)
- elif options.command == 'build':
- if langs:
- build_translations(src_subdir, build_subdir, langs)
- elif options.command == 'install':
- install_dir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], options.install_dir)
- if langs:
- build_translations(src_subdir, build_subdir, langs)
- merge_translations(build_subdir, abs_sources, langs)
- install_help(src_subdir, build_subdir, sources, media, langs, install_dir,
- destdir, options.project_id, options.symlinks)
- return 0
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index f2b59bd..c99e33c 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -14,6 +14,7 @@
from .. import mlog
import contextlib
+from dataclasses import dataclass
import urllib.request
import urllib.error
import urllib.parse
@@ -25,13 +26,14 @@ import stat
import subprocess
import sys
import configparser
+import time
import typing as T
import textwrap
from pathlib import Path
from . import WrapMode
from .. import coredata
-from ..mesonlib import quiet_git, GIT, ProgressBar, MesonException
+from ..mesonlib import quiet_git, GIT, ProgressBar, MesonException, windows_proof_rmtree
from ..interpreterbase import FeatureNew
from .. import mesonlib
@@ -203,13 +205,15 @@ def verbose_git(cmd: T.List[str], workingdir: str, check: bool = False) -> bool:
except mesonlib.GitException as e:
raise WrapException(str(e))
+@dataclass(eq=False)
class Resolver:
- def __init__(self, source_dir: str, subdir: str, subproject: str = '', wrap_mode: WrapMode = WrapMode.default) -> None:
- self.source_dir = source_dir
- self.subdir = subdir
- self.subproject = subproject
- self.wrap_mode = wrap_mode
- self.subdir_root = os.path.join(source_dir, subdir)
+ source_dir: str
+ subdir: str
+ subproject: str = ''
+ wrap_mode: WrapMode = WrapMode.default
+
+ def __post_init__(self) -> None:
+ self.subdir_root = os.path.join(self.source_dir, self.subdir)
self.cachedir = os.path.join(self.subdir_root, 'packagecache')
self.wraps = {} # type: T.Dict[str, PackageDefinition]
self.provided_deps = {} # type: T.Dict[str, PackageDefinition]
@@ -342,7 +346,11 @@ class Resolver:
self.get_svn()
else:
raise WrapException(f'Unknown wrap type {self.wrap.type!r}')
- self.apply_patch()
+ try:
+ self.apply_patch()
+ except:
+ windows_proof_rmtree(self.dirname)
+ raise
# A meson.build or CMakeLists.txt file is required in the directory
if method == 'meson' and not os.path.exists(meson_file):
@@ -527,12 +535,22 @@ class Resolver:
if dhash != expected:
raise WrapException(f'Incorrect hash for {what}:\n {expected} expected\n {dhash} actual.')
+ def get_data_with_backoff(self, urlstring: str) -> T.Tuple[str, str]:
+ delays = [1, 2, 4, 8, 16]
+ for d in delays:
+ try:
+ return self.get_data(urlstring)
+ except Exception as e:
+ mlog.warning(f'failed to download with error: {e}. Trying after a delay...', fatal=False)
+ time.sleep(d)
+ return self.get_data(urlstring)
+
def download(self, what: str, ofname: str, fallback: bool = False) -> None:
self.check_can_download()
srcurl = self.wrap.get(what + ('_fallback_url' if fallback else '_url'))
mlog.log('Downloading', mlog.bold(self.packagename), what, 'from', mlog.bold(srcurl))
try:
- dhash, tmpfile = self.get_data(srcurl)
+ dhash, tmpfile = self.get_data_with_backoff(srcurl)
expected = self.wrap.get(what + '_hash').lower()
if dhash != expected:
os.remove(tmpfile)
diff --git a/packaging/createmsi.py b/packaging/createmsi.py
index 0139877..d09fa78 100755
--- a/packaging/createmsi.py
+++ b/packaging/createmsi.py
@@ -125,7 +125,7 @@ class PackageGenerator:
self.staging_dirs = ['dist', 'dist2']
self.progfile_dir = 'ProgramFiles64Folder'
redist_globs = ['C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Redist\\MSVC\\v*\\MergeModules\\Microsoft_VC142_CRT_x64.msm',
- 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Preview\\VC\\Redist\\MSVC\\v*\\MergeModules\\Microsoft_VC143_CRT_x64.msm']
+ 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Redist\\MSVC\\v*\\MergeModules\\Microsoft_VC143_CRT_x64.msm']
redist_path = None
for g in redist_globs:
trials = glob(g)
diff --git a/run_meson_command_tests.py b/run_meson_command_tests.py
index 45096c6..36cb02e 100755
--- a/run_meson_command_tests.py
+++ b/run_meson_command_tests.py
@@ -70,7 +70,7 @@ class CommandTests(unittest.TestCase):
# between CI issue and test bug in that case. Set timeout and fail loud
# instead.
p = subprocess.run(command, stdout=subprocess.PIPE,
- env=os.environ.copy(), universal_newlines=True,
+ env=os.environ.copy(), text=True,
cwd=workdir, timeout=60 * 5)
print(p.stdout)
if p.returncode != 0:
diff --git a/run_mypy.py b/run_mypy.py
index 1c2d644..00d490b 100755
--- a/run_mypy.py
+++ b/run_mypy.py
@@ -25,6 +25,7 @@ modules = [
'mesonbuild/arglist.py',
'mesonbuild/backend/backends.py',
# 'mesonbuild/coredata.py',
+ 'mesonbuild/depfile.py',
'mesonbuild/envconfig.py',
'mesonbuild/interpreter/compiler.py',
'mesonbuild/interpreter/mesonmain.py',
@@ -40,6 +41,7 @@ modules = [
'mesonbuild/mlog.py',
'mesonbuild/msubprojects.py',
'mesonbuild/modules/fs.py',
+ 'mesonbuild/modules/gnome.py',
'mesonbuild/modules/i18n.py',
'mesonbuild/modules/java.py',
'mesonbuild/modules/keyval.py',
diff --git a/run_project_tests.py b/run_project_tests.py
index 822cf0b..5fea660 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -926,8 +926,7 @@ def have_d_compiler() -> bool:
# that exists but segfaults every time the compiler is run.
# Don't know why. Don't know how to fix. Skip in this case.
cp = subprocess.run(['dmd', '--version'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ capture_output=True)
if cp.stdout == b'':
return False
return True
diff --git a/run_tests.py b/run_tests.py
index b6f8884..20edf93 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -261,11 +261,10 @@ def ensure_backend_detects_changes(backend: Backend) -> None:
time.sleep(1)
def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str, str]:
- stderr = StringIO()
- stdout = StringIO()
- with mock.patch.object(sys, 'stdout', stdout), mock.patch.object(sys, 'stderr', stderr):
+ out = StringIO()
+ with mock.patch.object(sys, 'stdout', out), mock.patch.object(sys, 'stderr', out):
returncode = mtest.run_with_args(commandlist)
- return returncode, stdout.getvalue(), stderr.getvalue()
+ return returncode, stdout.getvalue()
def clear_meson_configure_class_caches() -> None:
compilers.CCompiler.find_library_cache = {}
diff --git a/setup.cfg b/setup.cfg
index c8c52ba..842e213 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -23,7 +23,6 @@ classifiers =
Operating System :: POSIX :: BSD
Operating System :: POSIX :: Linux
Programming Language :: Python :: 3 :: Only
- Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
@@ -32,7 +31,7 @@ long_description = Meson is a cross-platform build system designed to be both as
[options]
packages = find:
-python_requires = >= 3.6
+python_requires = >= 3.7
setup_requires =
setuptools
@@ -49,10 +48,11 @@ typing =
[options.package_data]
mesonbuild.scripts = cmd_or_ps.ps1
+mesonbuild.cmake.data = *
+mesonbuild.dependencies.data = *
[options.packages.find]
include = mesonbuild, mesonbuild.*
-exclude = *.data
[tool:pytest]
python_classes =
diff --git a/setup.py b/setup.py
index 976afb2..7ff28e2 100644
--- a/setup.py
+++ b/setup.py
@@ -16,9 +16,9 @@
import sys
-if sys.version_info < (3, 6):
+if sys.version_info < (3, 7):
raise SystemExit('ERROR: Tried to install Meson with an unsupported Python version: \n{}'
- '\nMeson requires Python 3.6.0 or greater'.format(sys.version))
+ '\nMeson requires Python 3.7.0 or greater'.format(sys.version))
from setuptools import setup
diff --git a/test cases/common/126 generated llvm ir/meson.build b/test cases/common/126 generated llvm ir/meson.build
index f10754a..fddee2b 100644
--- a/test cases/common/126 generated llvm ir/meson.build
+++ b/test cases/common/126 generated llvm ir/meson.build
@@ -5,7 +5,7 @@ if meson.get_compiler('c').get_id() != 'clang'
endif
if meson.backend() == 'xcode'
- error('MESON_SKIP_TEST: LLMV ir not supported with the Xcode backend. Patches welcome.')
+ error('MESON_SKIP_TEST: LLVM ir not supported with the Xcode backend. Patches welcome.')
endif
copy = find_program('copyfile.py')
diff --git a/test cases/common/14 configure file/meson.build b/test cases/common/14 configure file/meson.build
index 416dad7..91a56ff 100644
--- a/test cases/common/14 configure file/meson.build
+++ b/test cases/common/14 configure file/meson.build
@@ -275,9 +275,6 @@ configure_file(
test('configure-file', test_file)
-cdata = configuration_data()
-cdata.set('invalid_value', ['array'])
-
# Dictionaries
cdata = configuration_data({
diff --git a/test cases/common/187 args flattening/meson.build b/test cases/common/187 args flattening/meson.build
index 1dac2f9..61d77e4 100644
--- a/test cases/common/187 args flattening/meson.build
+++ b/test cases/common/187 args flattening/meson.build
@@ -6,13 +6,6 @@ assert(arr == ['bar', 'baz'], 'get_variable with array fallback is broken')
set_variable('arr', ['bar', 'baz'])
assert(arr == ['bar', 'baz'], 'set_variable(array) is broken')
-conf = configuration_data()
-conf.set('foo', ['bar', 'baz'])
-assert(conf.get('foo') == ['bar', 'baz'], 'configuration_data.set(array) is broken')
-
-arr = conf.get('does-not-exist', ['bar', 'baz'])
-assert(arr == ['bar', 'baz'], 'configuration_data.get with array fallback is broken')
-
arr = meson.get_cross_property('does-not-exist', ['bar', 'baz'])
assert(arr == ['bar', 'baz'], 'meson.get_cross_property with array fallback is broken')
@@ -27,5 +20,6 @@ assert(arr == ['bar', 'baz'], 'meson.get_external_property native:false with arr
# Test deprecated behaviour
+conf = configuration_data()
conf.set(['foo', 'bar'])
message(conf.get('foo'))
diff --git a/test cases/common/245 dependency fallbacks/meson.build b/test cases/common/246 dependency fallbacks/meson.build
index aaabaaa..aaabaaa 100644
--- a/test cases/common/245 dependency fallbacks/meson.build
+++ b/test cases/common/246 dependency fallbacks/meson.build
diff --git a/test cases/common/245 dependency fallbacks/subprojects/png/meson.build b/test cases/common/246 dependency fallbacks/subprojects/png/meson.build
index 5efc60a..5efc60a 100644
--- a/test cases/common/245 dependency fallbacks/subprojects/png/meson.build
+++ b/test cases/common/246 dependency fallbacks/subprojects/png/meson.build
diff --git a/test cases/common/245 deprecated option/meson.build b/test cases/common/247 deprecated option/meson.build
index 5102fd0..5102fd0 100644
--- a/test cases/common/245 deprecated option/meson.build
+++ b/test cases/common/247 deprecated option/meson.build
diff --git a/test cases/common/245 deprecated option/meson_options.txt b/test cases/common/247 deprecated option/meson_options.txt
index 5814531..5814531 100644
--- a/test cases/common/245 deprecated option/meson_options.txt
+++ b/test cases/common/247 deprecated option/meson_options.txt
diff --git a/test cases/common/245 deprecated option/test.json b/test cases/common/247 deprecated option/test.json
index c2f2ca3..c2f2ca3 100644
--- a/test cases/common/245 deprecated option/test.json
+++ b/test cases/common/247 deprecated option/test.json
diff --git a/test cases/common/246 install_emptydir/meson.build b/test cases/common/248 install_emptydir/meson.build
index a5eb046..a5eb046 100644
--- a/test cases/common/246 install_emptydir/meson.build
+++ b/test cases/common/248 install_emptydir/meson.build
diff --git a/test cases/common/246 install_emptydir/test.json b/test cases/common/248 install_emptydir/test.json
index 17abe74..17abe74 100644
--- a/test cases/common/246 install_emptydir/test.json
+++ b/test cases/common/248 install_emptydir/test.json
diff --git a/test cases/common/247 install_symlink/datafile.dat b/test cases/common/249 install_symlink/datafile.dat
index ff3104b..ff3104b 100644
--- a/test cases/common/247 install_symlink/datafile.dat
+++ b/test cases/common/249 install_symlink/datafile.dat
diff --git a/test cases/common/247 install_symlink/meson.build b/test cases/common/249 install_symlink/meson.build
index ae30382..ae30382 100644
--- a/test cases/common/247 install_symlink/meson.build
+++ b/test cases/common/249 install_symlink/meson.build
diff --git a/test cases/common/247 install_symlink/test.json b/test cases/common/249 install_symlink/test.json
index 33aa76e..33aa76e 100644
--- a/test cases/common/247 install_symlink/test.json
+++ b/test cases/common/249 install_symlink/test.json
diff --git a/test cases/common/250 system include dir/lib/lib.hpp b/test cases/common/250 system include dir/lib/lib.hpp
new file mode 100644
index 0000000..a1fbf85
--- /dev/null
+++ b/test cases/common/250 system include dir/lib/lib.hpp
@@ -0,0 +1,4 @@
+#pragma once
+
+// This will trigger -Wsign-conversion
+inline unsigned convert_to_unsigned(int i) { return i; }
diff --git a/test cases/common/250 system include dir/main.cpp b/test cases/common/250 system include dir/main.cpp
new file mode 100644
index 0000000..9f83297
--- /dev/null
+++ b/test cases/common/250 system include dir/main.cpp
@@ -0,0 +1,3 @@
+#include <lib.hpp>
+
+int main() { return 0; }
diff --git a/test cases/common/250 system include dir/meson.build b/test cases/common/250 system include dir/meson.build
new file mode 100644
index 0000000..724a8e4
--- /dev/null
+++ b/test cases/common/250 system include dir/meson.build
@@ -0,0 +1,13 @@
+project('system_include_dir', 'cpp',
+ version : '0.1',
+ default_options : 'werror=true',
+)
+
+compiler_id = meson.get_compiler('cpp').get_id()
+if not ['gcc', 'clang', 'clang-cl'].contains(compiler_id)
+ error('MESON_SKIP_TEST: compiler @0@ either doesn\'t support is_system includes or needs to have support for this test added'.format(compiler_id))
+endif
+
+lib_include_directories = include_directories('lib', is_system: true)
+add_project_arguments('-Wsign-conversion', language: 'cpp')
+executable('system_include_dir_test', sources: 'main.cpp', include_directories: lib_include_directories)
diff --git a/test cases/common/44 pkgconfig-gen/answer.c b/test cases/common/44 pkgconfig-gen/answer.c
new file mode 100644
index 0000000..df5f54f
--- /dev/null
+++ b/test cases/common/44 pkgconfig-gen/answer.c
@@ -0,0 +1,3 @@
+int answer_to_life_the_universe_and_everything(void) {
+ return 42;
+}
diff --git a/test cases/common/44 pkgconfig-gen/foo.c b/test cases/common/44 pkgconfig-gen/foo.c
new file mode 100644
index 0000000..83bb06a
--- /dev/null
+++ b/test cases/common/44 pkgconfig-gen/foo.c
@@ -0,0 +1,7 @@
+#include"simple.h"
+
+int answer_to_life_the_universe_and_everything (void);
+
+int simple_function(void) {
+ return answer_to_life_the_universe_and_everything();
+}
diff --git a/test cases/common/44 pkgconfig-gen/meson.build b/test cases/common/44 pkgconfig-gen/meson.build
index 87c0767..128205a 100644
--- a/test cases/common/44 pkgconfig-gen/meson.build
+++ b/test cases/common/44 pkgconfig-gen/meson.build
@@ -18,6 +18,8 @@ if v.version_compare('<0.29')
error('MESON_SKIP_TEST: pkg-config version \'' + v + '\' too old')
endif
+python = import('python').find_installation()
+fs = import('fs')
pkgg = import('pkgconfig')
lib = shared_library('simple', 'simple.c')
@@ -40,13 +42,22 @@ test('pkgconfig-validation', pkgconfig,
args: ['--validate', 'simple'],
env: [ 'PKG_CONFIG_PATH=' + meson.current_build_dir() + '/meson-private' ])
+answerlib = shared_library('answer', 'answer.c')
+
+pkgg.generate(answerlib,
+ name : 'libanswer',
+ description : 'An answer library.',
+ extra_cflags : ['-DLIBFOO'],
+)
+
# Test that name_prefix='' and name='libfoo' results in '-lfoo'
-lib2 = shared_library('libfoo', 'simple.c',
+lib2 = shared_library('libfoo', 'foo.c',
+ link_with: answerlib,
name_prefix : '',
version : libver)
-pkgg.generate(
- libraries : lib2,
+pkgg.generate(lib2,
+ libraries : [lib2, answerlib],
name : 'libfoo',
version : libver,
description : 'A foo library.',
@@ -124,3 +135,17 @@ if cc.get_id() in ['gcc', 'clang']
description: 'custom target index'
)
endif
+
+# Regression test: A library linking to an uninstalled custom_target static
+# library used to crash when generating its pkgconfig file.
+# Copy libstat2.a to libstat3.a to have a static library as custom target.
+infile = stat2.full_path()
+outfile = meson.current_build_dir() / 'libstat3.a'
+script = 'import shutil ; shutil.copyfile("@0@", "@1@")'.format(infile, outfile)
+ct = custom_target('stat3',
+ input: stat2,
+ output: fs.name(outfile),
+ command: [python, '-c', script],
+)
+simple6 = library('simple6', link_with: ct)
+pkgg.generate(simple6)
diff --git a/test cases/common/44 pkgconfig-gen/test.json b/test cases/common/44 pkgconfig-gen/test.json
index e741a62..c7bdd43 100644
--- a/test cases/common/44 pkgconfig-gen/test.json
+++ b/test cases/common/44 pkgconfig-gen/test.json
@@ -3,12 +3,14 @@
{"type": "file", "file": "usr/include/simple.h"},
{"type": "file", "file": "usr/lib/libstat2.a"},
{"type": "file", "file": "usr/lib/pkgconfig/simple.pc"},
+ {"type": "file", "file": "usr/lib/pkgconfig/libanswer.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/libfoo.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/libhello.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/libhello_nolib.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/simple2.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/simple3.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/simple5.pc"},
+ {"type": "file", "file": "usr/lib/pkgconfig/simple6.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/ct.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/ct0.pc"}
]
diff --git a/test cases/failing/101 no glib-compile-resources/test.json b/test cases/failing/101 no glib-compile-resources/test.json
index d81b0c0..7f0c02c 100644
--- a/test cases/failing/101 no glib-compile-resources/test.json
+++ b/test cases/failing/101 no glib-compile-resources/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/101 no glib-compile-resources/meson.build:8:0: ERROR: Program 'glib-compile-resources' not found"
+ "line": "test cases/failing/101 no glib-compile-resources/meson.build:8:0: ERROR: Program 'glib-compile-resources' not found or not executable"
}
]
}
diff --git a/test cases/failing/106 feature require.bis/meson.build b/test cases/failing/107 feature require.bis/meson.build
index 08c099c..08c099c 100644
--- a/test cases/failing/106 feature require.bis/meson.build
+++ b/test cases/failing/107 feature require.bis/meson.build
diff --git a/test cases/failing/106 feature require.bis/meson_options.txt b/test cases/failing/107 feature require.bis/meson_options.txt
index 5910a87..5910a87 100644
--- a/test cases/failing/106 feature require.bis/meson_options.txt
+++ b/test cases/failing/107 feature require.bis/meson_options.txt
diff --git a/test cases/failing/106 feature require.bis/test.json b/test cases/failing/107 feature require.bis/test.json
index 2583990..2583990 100644
--- a/test cases/failing/106 feature require.bis/test.json
+++ b/test cases/failing/107 feature require.bis/test.json
diff --git a/test cases/failing/107 no build get_external_property/meson.build b/test cases/failing/108 no build get_external_property/meson.build
index 8a4215c..8a4215c 100644
--- a/test cases/failing/107 no build get_external_property/meson.build
+++ b/test cases/failing/108 no build get_external_property/meson.build
diff --git a/test cases/failing/107 no build get_external_property/test.json b/test cases/failing/108 no build get_external_property/test.json
index b95427e..d2827f4 100644
--- a/test cases/failing/107 no build get_external_property/test.json
+++ b/test cases/failing/108 no build get_external_property/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/107 no build get_external_property/meson.build:3:0: ERROR: Unknown property for build machine: nonexisting"
+ "line": "test cases/failing/108 no build get_external_property/meson.build:3:0: ERROR: Unknown property for build machine: nonexisting"
}
]
}
diff --git a/test cases/failing/108 enter subdir twice/meson.build b/test cases/failing/109 enter subdir twice/meson.build
index 9343233..9343233 100644
--- a/test cases/failing/108 enter subdir twice/meson.build
+++ b/test cases/failing/109 enter subdir twice/meson.build
diff --git a/test cases/failing/108 enter subdir twice/sub/meson.build b/test cases/failing/109 enter subdir twice/sub/meson.build
index d036a3f..d036a3f 100644
--- a/test cases/failing/108 enter subdir twice/sub/meson.build
+++ b/test cases/failing/109 enter subdir twice/sub/meson.build
diff --git a/test cases/failing/108 enter subdir twice/test.json b/test cases/failing/109 enter subdir twice/test.json
index 0a8e127..f7a526c 100644
--- a/test cases/failing/108 enter subdir twice/test.json
+++ b/test cases/failing/109 enter subdir twice/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/108 enter subdir twice/meson.build:3:0: ERROR: Tried to enter directory \"sub\", which has already been visited."
+ "line": "test cases/failing/109 enter subdir twice/meson.build:3:0: ERROR: Tried to enter directory \"sub\", which has already been visited."
}
]
}
diff --git a/test cases/failing/109 invalid fstring/meson.build b/test cases/failing/111 invalid fstring/109 invalid fstring/meson.build
index dd22f56..dd22f56 100644
--- a/test cases/failing/109 invalid fstring/meson.build
+++ b/test cases/failing/111 invalid fstring/109 invalid fstring/meson.build
diff --git a/test cases/failing/109 invalid fstring/test.json b/test cases/failing/111 invalid fstring/109 invalid fstring/test.json
index 71d8f59..71d8f59 100644
--- a/test cases/failing/109 invalid fstring/test.json
+++ b/test cases/failing/111 invalid fstring/109 invalid fstring/test.json
diff --git a/test cases/failing/110 invalid fstring/meson.build b/test cases/failing/111 invalid fstring/meson.build
index 973df30..973df30 100644
--- a/test cases/failing/110 invalid fstring/meson.build
+++ b/test cases/failing/111 invalid fstring/meson.build
diff --git a/test cases/failing/110 invalid fstring/test.json b/test cases/failing/111 invalid fstring/test.json
index bfd0e2d..89ec40c 100644
--- a/test cases/failing/110 invalid fstring/test.json
+++ b/test cases/failing/111 invalid fstring/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/110 invalid fstring/meson.build:3:0: ERROR: Identifier \"foo\" does not name a variable."
+ "line": "test cases/failing/111 invalid fstring/meson.build:3:0: ERROR: Identifier \"foo\" does not name a variable."
}
]
}
diff --git a/test cases/failing/111 compiler argument checking/meson.build b/test cases/failing/112 compiler argument checking/meson.build
index bb1f447..bb1f447 100644
--- a/test cases/failing/111 compiler argument checking/meson.build
+++ b/test cases/failing/112 compiler argument checking/meson.build
diff --git a/test cases/failing/111 compiler argument checking/test.json b/test cases/failing/112 compiler argument checking/test.json
index f41f2d2..f4728db 100644
--- a/test cases/failing/111 compiler argument checking/test.json
+++ b/test cases/failing/112 compiler argument checking/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/111 compiler argument checking/meson.build:4:0: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\""
+ "line": "test cases/failing/112 compiler argument checking/meson.build:4:0: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\""
}
]
}
diff --git a/test cases/failing/112 empty fallback/meson.build b/test cases/failing/113 empty fallback/meson.build
index f4eb5fe..f4eb5fe 100644
--- a/test cases/failing/112 empty fallback/meson.build
+++ b/test cases/failing/113 empty fallback/meson.build
diff --git a/test cases/failing/112 empty fallback/subprojects/foo/meson.build b/test cases/failing/113 empty fallback/subprojects/foo/meson.build
index c9e134b..c9e134b 100644
--- a/test cases/failing/112 empty fallback/subprojects/foo/meson.build
+++ b/test cases/failing/113 empty fallback/subprojects/foo/meson.build
diff --git a/test cases/failing/112 empty fallback/test.json b/test cases/failing/113 empty fallback/test.json
index 89520ef..c8ed212 100644
--- a/test cases/failing/112 empty fallback/test.json
+++ b/test cases/failing/113 empty fallback/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/112 empty fallback/meson.build:6:0: ERROR: Dependency \"foo\" not found, tried pkgconfig and cmake"
+ "line": "test cases/failing/113 empty fallback/meson.build:6:0: ERROR: Dependency \"foo\" not found, tried pkgconfig and cmake"
}
]
}
diff --git a/test cases/failing/113 cmake executable dependency/meson.build b/test cases/failing/114 cmake executable dependency/meson.build
index bfb03ef..bfb03ef 100644
--- a/test cases/failing/113 cmake executable dependency/meson.build
+++ b/test cases/failing/114 cmake executable dependency/meson.build
diff --git a/test cases/failing/113 cmake executable dependency/subprojects/cmlib/CMakeLists.txt b/test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt
index 0067879..0067879 100644
--- a/test cases/failing/113 cmake executable dependency/subprojects/cmlib/CMakeLists.txt
+++ b/test cases/failing/114 cmake executable dependency/subprojects/cmlib/CMakeLists.txt
diff --git a/test cases/failing/113 cmake executable dependency/subprojects/cmlib/main.c b/test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c
index 9b6bdc2..9b6bdc2 100644
--- a/test cases/failing/113 cmake executable dependency/subprojects/cmlib/main.c
+++ b/test cases/failing/114 cmake executable dependency/subprojects/cmlib/main.c
diff --git a/test cases/failing/113 cmake executable dependency/test.json b/test cases/failing/114 cmake executable dependency/test.json
index 1cb4a0f..82306dd 100644
--- a/test cases/failing/113 cmake executable dependency/test.json
+++ b/test cases/failing/114 cmake executable dependency/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/113 cmake executable dependency/meson.build:9:0: ERROR: main is an executable and does not support the dependency() method. Use target() instead."
+ "line": "test cases/failing/114 cmake executable dependency/meson.build:9:0: ERROR: main is an executable and does not support the dependency() method. Use target() instead."
}
]
}
diff --git a/test cases/failing/114 allow_fallback with fallback/meson.build b/test cases/failing/115 allow_fallback with fallback/meson.build
index 2874e42..2874e42 100644
--- a/test cases/failing/114 allow_fallback with fallback/meson.build
+++ b/test cases/failing/115 allow_fallback with fallback/meson.build
diff --git a/test cases/failing/114 allow_fallback with fallback/test.json b/test cases/failing/115 allow_fallback with fallback/test.json
index 1e5712e..6bdcc51 100644
--- a/test cases/failing/114 allow_fallback with fallback/test.json
+++ b/test cases/failing/115 allow_fallback with fallback/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/114 allow_fallback with fallback/meson.build:3:0: ERROR: \"fallback\" and \"allow_fallback\" arguments are mutually exclusive"
+ "line": "test cases/failing/115 allow_fallback with fallback/meson.build:3:0: ERROR: \"fallback\" and \"allow_fallback\" arguments are mutually exclusive"
}
]
}
diff --git a/test cases/failing/115 nonsensical bindgen/meson.build b/test cases/failing/116 nonsensical bindgen/meson.build
index 6995f67..6995f67 100644
--- a/test cases/failing/115 nonsensical bindgen/meson.build
+++ b/test cases/failing/116 nonsensical bindgen/meson.build
diff --git a/test cases/failing/115 nonsensical bindgen/src/header.h b/test cases/failing/116 nonsensical bindgen/src/header.h
index 750621f..750621f 100644
--- a/test cases/failing/115 nonsensical bindgen/src/header.h
+++ b/test cases/failing/116 nonsensical bindgen/src/header.h
diff --git a/test cases/failing/115 nonsensical bindgen/src/source.c b/test cases/failing/116 nonsensical bindgen/src/source.c
index d652d28..d652d28 100644
--- a/test cases/failing/115 nonsensical bindgen/src/source.c
+++ b/test cases/failing/116 nonsensical bindgen/src/source.c
diff --git a/test cases/failing/115 nonsensical bindgen/test.json b/test cases/failing/116 nonsensical bindgen/test.json
index d9249b2..b0a38e8 100644
--- a/test cases/failing/115 nonsensical bindgen/test.json
+++ b/test cases/failing/116 nonsensical bindgen/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/115 nonsensical bindgen/meson.build:17:24: ERROR: bindgen source file must be a C header, not an object or build target"
+ "line": "test cases/failing/116 nonsensical bindgen/meson.build:17:24: ERROR: bindgen source file must be a C header, not an object or build target"
}
]
}
diff --git a/test cases/failing/116 run_target in test/meson.build b/test cases/failing/117 run_target in test/meson.build
index db7cb30..db7cb30 100644
--- a/test cases/failing/116 run_target in test/meson.build
+++ b/test cases/failing/117 run_target in test/meson.build
diff --git a/test cases/failing/116 run_target in test/test.json b/test cases/failing/117 run_target in test/test.json
index 961c1e4..ad24367 100644
--- a/test cases/failing/116 run_target in test/test.json
+++ b/test cases/failing/117 run_target in test/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/116 run_target in test/meson.build:4:0: ERROR: test keyword argument 'args' was of type array[RunTarget] but should have been array[str | File | BuildTarget | CustomTarget | CustomTargetIndex]"
+ "line": "test cases/failing/117 run_target in test/meson.build:4:0: ERROR: test keyword argument 'args' was of type array[RunTarget] but should have been array[str | File | BuildTarget | CustomTarget | CustomTargetIndex]"
}
]
}
diff --git a/test cases/failing/116 run_target in test/trivial.c b/test cases/failing/117 run_target in test/trivial.c
index 96612d4..96612d4 100644
--- a/test cases/failing/116 run_target in test/trivial.c
+++ b/test cases/failing/117 run_target in test/trivial.c
diff --git a/test cases/failing/117 run_target in add_install_script/meson.build b/test cases/failing/118 run_target in add_install_script/meson.build
index 9d37a39..9d37a39 100644
--- a/test cases/failing/117 run_target in add_install_script/meson.build
+++ b/test cases/failing/118 run_target in add_install_script/meson.build
diff --git a/test cases/failing/117 run_target in add_install_script/test.json b/test cases/failing/118 run_target in add_install_script/test.json
index fec1941..a09b1a3 100644
--- a/test cases/failing/117 run_target in add_install_script/test.json
+++ b/test cases/failing/118 run_target in add_install_script/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/117 run_target in add_install_script/meson.build:4:6: ERROR: meson.add_install_script argument 2 was of type \"RunTarget\" but should have been one of: \"str\", \"File\", \"BuildTarget\", \"CustomTarget\", \"CustomTargetIndex\", \"ExternalProgram\""
+ "line": "test cases/failing/118 run_target in add_install_script/meson.build:4:6: ERROR: meson.add_install_script argument 2 was of type \"RunTarget\" but should have been one of: \"str\", \"File\", \"BuildTarget\", \"CustomTarget\", \"CustomTargetIndex\", \"ExternalProgram\""
}
]
}
diff --git a/test cases/failing/117 run_target in add_install_script/trivial.c b/test cases/failing/118 run_target in add_install_script/trivial.c
index 1b14571..1b14571 100644
--- a/test cases/failing/117 run_target in add_install_script/trivial.c
+++ b/test cases/failing/118 run_target in add_install_script/trivial.c
diff --git a/test cases/failing/118 pathsep in install_symlink/meson.build b/test cases/failing/119 pathsep in install_symlink/meson.build
index cce82c2..cce82c2 100644
--- a/test cases/failing/118 pathsep in install_symlink/meson.build
+++ b/test cases/failing/119 pathsep in install_symlink/meson.build
diff --git a/test cases/failing/118 pathsep in install_symlink/test.json b/test cases/failing/119 pathsep in install_symlink/test.json
index e3f3a4a..9df546a 100644
--- a/test cases/failing/118 pathsep in install_symlink/test.json
+++ b/test cases/failing/119 pathsep in install_symlink/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/118 pathsep in install_symlink/meson.build:3:0: ERROR: Link name is \"foo/bar\", but link names cannot contain path separators. The dir part should be in install_dir."
+ "line": "test cases/failing/119 pathsep in install_symlink/meson.build:3:0: ERROR: Link name is \"foo/bar\", but link names cannot contain path separators. The dir part should be in install_dir."
}
]
}
diff --git a/test cases/failing/120 subproject version conflict/meson.build b/test cases/failing/120 subproject version conflict/meson.build
new file mode 100644
index 0000000..ffbcc13
--- /dev/null
+++ b/test cases/failing/120 subproject version conflict/meson.build
@@ -0,0 +1,4 @@
+project('120 subproject version conflict')
+
+A_dep = subproject('A').get_variable('A_dep')
+B_dep = subproject('B', version: '1').get_variable('B_dep')
diff --git a/test cases/failing/120 subproject version conflict/subprojects/A/meson.build b/test cases/failing/120 subproject version conflict/subprojects/A/meson.build
new file mode 100644
index 0000000..7da4df0
--- /dev/null
+++ b/test cases/failing/120 subproject version conflict/subprojects/A/meson.build
@@ -0,0 +1,4 @@
+project('A')
+
+B_dep = subproject('B').get_variable('B_dep')
+A_dep = declare_dependency(dependencies: B_dep)
diff --git a/test cases/failing/120 subproject version conflict/subprojects/B/meson.build b/test cases/failing/120 subproject version conflict/subprojects/B/meson.build
new file mode 100644
index 0000000..0ead934
--- /dev/null
+++ b/test cases/failing/120 subproject version conflict/subprojects/B/meson.build
@@ -0,0 +1,3 @@
+project('B', version: '100')
+
+B_dep = declare_dependency()
diff --git a/test cases/failing/120 subproject version conflict/test.json b/test cases/failing/120 subproject version conflict/test.json
new file mode 100644
index 0000000..5d445e5
--- /dev/null
+++ b/test cases/failing/120 subproject version conflict/test.json
@@ -0,0 +1,7 @@
+{
+ "stdout": [
+ {
+ "line": "test cases/failing/120 subproject version conflict/meson.build:4:0: ERROR: Subproject B version is 100 but 1 required."
+ }
+ ]
+}
diff --git a/test cases/unit/98 install all targets/bar-notag.txt b/test cases/frameworks/10 gtk-doc/doc/foobar1/baz.jpg
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/bar-notag.txt
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar1/baz.jpg
diff --git a/test cases/unit/98 install all targets/foo.in b/test cases/frameworks/10 gtk-doc/doc/foobar1/baz.png.in
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/foo.in
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar1/baz.png.in
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build b/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build
index f4b3724..2af9670 100644
--- a/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar1/meson.build
@@ -1,9 +1,15 @@
+png = configure_file(input: 'baz.png.in',
+ output: 'baz.png',
+ copy: true)
+
gnome.gtkdoc('foobar',
src_dir : [inc, '.'],
main_sgml : 'foobar-docs.sgml',
content_files : [docbook, version_xml],
dependencies: foo_dep,
+ html_assets: ['baz.jpg', png],
# Manually written types file for regression test:
# https://github.com/mesonbuild/meson/issues/8744
gobject_typesfile: 'foobar.types',
- install : true)
+ install : true,
+ check: false)
diff --git a/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build b/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build
index 0b2faa0..5f860ef 100644
--- a/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build
+++ b/test cases/frameworks/10 gtk-doc/doc/foobar2/meson.build
@@ -1,6 +1,13 @@
+types = configure_file(input: '../foobar1/foobar.types',
+ output: 'foobar.types',
+ copy: true
+)
+
gnome.gtkdoc('foobar2',
src_dir : inc,
main_sgml : 'foobar-docs.sgml',
content_files : [docbook, version_xml],
+ gobject_typesfile: types,
+ dependencies: foo_dep,
install : true,
install_dir : 'foobar2')
diff --git a/test cases/frameworks/10 gtk-doc/test.json b/test cases/frameworks/10 gtk-doc/test.json
index edade39..f2805d3 100644
--- a/test cases/frameworks/10 gtk-doc/test.json
+++ b/test cases/frameworks/10 gtk-doc/test.json
@@ -2,6 +2,8 @@
"installed": [
{"type": "file", "file": "usr/include/foo-version.h"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/BAR.html"},
+ {"type": "file", "file": "usr/share/gtk-doc/html/foobar/baz.jpg"},
+ {"type": "file", "file": "usr/share/gtk-doc/html/foobar/baz.png"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/foobar.devhelp2"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/foobar.html"},
{"type": "file", "file": "usr/share/gtk-doc/html/foobar/FooObj.html"},
diff --git a/test cases/frameworks/13 yelp/help/C/index2.page b/test cases/frameworks/13 yelp/help/C/index2.page
new file mode 100644
index 0000000..14b6b51
--- /dev/null
+++ b/test cases/frameworks/13 yelp/help/C/index2.page
@@ -0,0 +1,8 @@
+<page xmlns="http://projectmallard.org/1.0/"
+ xmlns:its="http://www.w3.org/2005/11/its"
+ type="guide"
+ id="index2">
+ <title>
+ Hello!
+ </title>
+</page>
diff --git a/test cases/frameworks/13 yelp/help/C/index3.page b/test cases/frameworks/13 yelp/help/C/index3.page
new file mode 100644
index 0000000..c0c21c1
--- /dev/null
+++ b/test cases/frameworks/13 yelp/help/C/index3.page
@@ -0,0 +1,8 @@
+<page xmlns="http://projectmallard.org/1.0/"
+ xmlns:its="http://www.w3.org/2005/11/its"
+ type="guide"
+ id="index3">
+ <title>
+ Hello!
+ </title>
+</page>
diff --git a/test cases/frameworks/13 yelp/help/meson.build b/test cases/frameworks/13 yelp/help/meson.build
index c8edd61..d6dbe10 100644
--- a/test cases/frameworks/13 yelp/help/meson.build
+++ b/test cases/frameworks/13 yelp/help/meson.build
@@ -8,14 +8,14 @@ gnome.yelp('meson',
)
gnome.yelp('meson-symlink',
- sources: 'index.page',
+ sources: 'index2.page',
media: 'media/test.txt',
symlink_media: true,
languages: ['de', 'es'],
)
gnome.yelp('meson-linguas',
- sources: 'index.page',
+ sources: 'index3.page',
media: 'media/test.txt',
symlink_media: false,
)
diff --git a/test cases/frameworks/13 yelp/test.json b/test cases/frameworks/13 yelp/test.json
index ffe75cb..22e34d2 100644
--- a/test cases/frameworks/13 yelp/test.json
+++ b/test cases/frameworks/13 yelp/test.json
@@ -6,17 +6,17 @@
{"type": "file", "file": "usr/share/help/es/meson/media/test.txt"},
{"type": "file", "file": "usr/share/help/de/meson/index.page"},
{"type": "file", "file": "usr/share/help/de/meson/media/test.txt"},
- {"type": "file", "file": "usr/share/help/C/meson-symlink/index.page"},
+ {"type": "file", "file": "usr/share/help/C/meson-symlink/index2.page"},
{"type": "file", "file": "usr/share/help/C/meson-symlink/media/test.txt"},
+ {"type": "file", "file": "usr/share/help/es/meson-symlink/index2.page"},
{"type": "file", "file": "usr/share/help/es/meson-symlink/media/test.txt"},
- {"type": "file", "file": "usr/share/help/es/meson-symlink/index.page"},
- {"type": "file", "file": "usr/share/help/de/meson-symlink/index.page"},
+ {"type": "file", "file": "usr/share/help/de/meson-symlink/index2.page"},
{"type": "file", "file": "usr/share/help/de/meson-symlink/media/test.txt"},
- {"type": "file", "file": "usr/share/help/C/meson-linguas/index.page"},
+ {"type": "file", "file": "usr/share/help/C/meson-linguas/index3.page"},
{"type": "file", "file": "usr/share/help/C/meson-linguas/media/test.txt"},
+ {"type": "file", "file": "usr/share/help/es/meson-linguas/index3.page"},
{"type": "file", "file": "usr/share/help/es/meson-linguas/media/test.txt"},
- {"type": "file", "file": "usr/share/help/es/meson-linguas/index.page"},
- {"type": "file", "file": "usr/share/help/de/meson-linguas/index.page"},
+ {"type": "file", "file": "usr/share/help/de/meson-linguas/index3.page"},
{"type": "file", "file": "usr/share/help/de/meson-linguas/media/test.txt"}
],
"skip_on_jobname": ["azure", "cygwin", "macos", "msys2"]
diff --git a/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml b/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml
index 9ece885..d7adc30 100644
--- a/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml
+++ b/test cases/frameworks/7 gnome/gdbus/data/com.example.Sample.xml
@@ -6,5 +6,9 @@
<arg direction="in" type="s" name="name"/>
<arg direction="out" type="s" name="greeting"/>
</method>
+ <method name="Bye">
+ <arg direction="in" type="s" name="name"/>
+ <arg direction="out" type="s" name="greeting"/>
+ </method>
</interface>
</node>
diff --git a/test cases/frameworks/7 gnome/gdbus/meson.build b/test cases/frameworks/7 gnome/gdbus/meson.build
index 2de172f..a786d24 100644
--- a/test cases/frameworks/7 gnome/gdbus/meson.build
+++ b/test cases/frameworks/7 gnome/gdbus/meson.build
@@ -10,12 +10,29 @@ assert(gdbus_src.length() == 2, 'expected 2 targets')
assert(gdbus_src[0].full_path().endswith('.c'), 'expected 1 c source file')
assert(gdbus_src[1].full_path().endswith('.h'), 'expected 1 c header file')
+sample_xml = configure_file(input: 'data/com.example.Sample.xml',
+ output: 'com.example.Sample.xml',
+ copy: true)
+
+gdbus_src = gnome.gdbus_codegen('generated-gdbus-no-docbook-files-posarg',
+ sample_xml,
+ interface_prefix : 'com.example.',
+ namespace : 'Sample',
+ annotations : [
+ ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true']
+ ],
+)
+assert(gdbus_src.length() == 2, 'expected 2 targets')
+assert(gdbus_src[0].full_path().endswith('.c'), 'expected 1 c source file')
+assert(gdbus_src[1].full_path().endswith('.h'), 'expected 1 c header file')
+
gdbus_src = gnome.gdbus_codegen('generated-gdbus',
sources : files('data/com.example.Sample.xml'),
interface_prefix : 'com.example.',
namespace : 'Sample',
annotations : [
- ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true']
+ ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true'],
+ ['com.example.Bye()', 'org.freedesktop.DBus.Deprecated', 'true'],
],
docbook : 'generated-gdbus-doc',
install_header : true,
diff --git a/test cases/frameworks/7 gnome/genmarshal/main.c b/test cases/frameworks/7 gnome/genmarshal/main.c.in
index 83b08af..8e3ca7a 100644
--- a/test cases/frameworks/7 gnome/genmarshal/main.c
+++ b/test cases/frameworks/7 gnome/genmarshal/main.c.in
@@ -1,7 +1,7 @@
-#include<stdio.h>
-#include<stdlib.h>
-#include<glib-object.h>
-#include"marshaller.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib-object.h>
+#include @MARSHALLER_HEADER@
static int singleton = 42;
diff --git a/test cases/frameworks/7 gnome/genmarshal/meson.build b/test cases/frameworks/7 gnome/genmarshal/meson.build
index d7189f5..7686b4b 100644
--- a/test cases/frameworks/7 gnome/genmarshal/meson.build
+++ b/test cases/frameworks/7 gnome/genmarshal/meson.build
@@ -1,12 +1,51 @@
-marshallers = gnome.genmarshal('marshaller',
-sources : 'marshaller.list',
-install_header : true,
-install_dir : get_option('includedir'),
-extra_args : ['-UG_ENABLE_DEBUG', '--prototypes'])
-
-marshaller_c = marshallers[0]
-marshaller_h = marshallers[1]
-
-genmarshalexe = executable('genmarshalprog', 'main.c', marshaller_c, marshaller_h,
-dependencies : gobj)
-test('genmarshal test', genmarshalexe)
+m_list = configure_file(input: 'marshaller.list',
+ output: 'm.list',
+ copy: true)
+
+idx = 0
+mlists = ['marshaller.list', files('marshaller.list'), m_list]
+
+foreach mlist : mlists
+ marshallers = gnome.genmarshal('marshaller-@0@'.format(idx),
+ sources : mlist,
+ install_header : true,
+ install_dir : get_option('includedir') / 'subdir-@0@'.format(idx),
+ extra_args : ['-UG_ENABLE_DEBUG', '--prototypes'])
+
+ marshaller_c = marshallers[0]
+ marshaller_h = marshallers[1]
+
+ cdata = configuration_data()
+ cdata.set_quoted('MARSHALLER_HEADER', 'marshaller-@0@.h'.format(idx))
+
+ main_c = configure_file(input: 'main.c.in',
+ output: 'main-@0@.c'.format(idx),
+ configuration: cdata)
+
+ genmarshalexe = executable('genmarshalprog-@0@'.format(idx),
+ main_c, marshaller_c, marshaller_h,
+ dependencies : gobj)
+ test('genmarshal test @0@'.format(idx), genmarshalexe)
+ idx += 1
+endforeach
+
+foreach mlist : mlists
+ marshallers = gnome.genmarshal('marshaller-@0@'.format(idx),
+ sources : [mlist],
+ install_header : true,
+ install_dir : get_option('includedir') / 'subdir-@0@'.format(idx),
+ extra_args : ['-UG_ENABLE_DEBUG', '--prototypes'])
+
+ marshaller_c = marshallers[0]
+ marshaller_h = marshallers[1]
+
+ main_c = configure_file(input: 'main.c.in',
+ output: 'main-@0@.c'.format(idx),
+ configuration: cdata)
+
+ genmarshalexe = executable('genmarshalprog-@0@'.format(idx),
+ main_c, marshaller_c, marshaller_h,
+ dependencies : gobj)
+ test('genmarshal test @0@'.format(idx), genmarshalexe)
+ idx += 1
+endforeach
diff --git a/test cases/frameworks/7 gnome/test.json b/test cases/frameworks/7 gnome/test.json
index d243cff..0d17384 100644
--- a/test cases/frameworks/7 gnome/test.json
+++ b/test cases/frameworks/7 gnome/test.json
@@ -4,7 +4,12 @@
{"type": "file", "file": "usr/include/enums2.h"},
{"type": "file", "file": "usr/include/enums3.h"},
{"type": "file", "file": "usr/include/enums5.h"},
- {"type": "file", "file": "usr/include/marshaller.h"},
+ {"type": "file", "file": "usr/include/subdir-0/marshaller-0.h"},
+ {"type": "file", "file": "usr/include/subdir-1/marshaller-1.h"},
+ {"type": "file", "file": "usr/include/subdir-2/marshaller-2.h"},
+ {"type": "file", "file": "usr/include/subdir-3/marshaller-3.h"},
+ {"type": "file", "file": "usr/include/subdir-4/marshaller-4.h"},
+ {"type": "file", "file": "usr/include/subdir-5/marshaller-5.h"},
{"type": "expr", "file": "usr/lib/?libgir_lib.so"},
{"type": "file", "platform": "cygwin", "file": "usr/lib/libgir_lib.dll.a"},
{"type": "expr", "file": "usr/lib/?libgir_lib2.so"},
diff --git a/test cases/unit/99 custom target name/file.txt.in b/test cases/unit/100 custom target name/file.txt.in
index e69de29..e69de29 100644
--- a/test cases/unit/99 custom target name/file.txt.in
+++ b/test cases/unit/100 custom target name/file.txt.in
diff --git a/test cases/unit/99 custom target name/meson.build b/test cases/unit/100 custom target name/meson.build
index 8d148a8..8d148a8 100644
--- a/test cases/unit/99 custom target name/meson.build
+++ b/test cases/unit/100 custom target name/meson.build
diff --git a/test cases/unit/99 custom target name/subdir/meson.build b/test cases/unit/100 custom target name/subdir/meson.build
index 785a7b3..785a7b3 100644
--- a/test cases/unit/99 custom target name/subdir/meson.build
+++ b/test cases/unit/100 custom target name/subdir/meson.build
diff --git a/test cases/unit/99 relative find program/foo.py b/test cases/unit/101 relative find program/foo.py
index 21239b7..21239b7 100755
--- a/test cases/unit/99 relative find program/foo.py
+++ b/test cases/unit/101 relative find program/foo.py
diff --git a/test cases/unit/99 relative find program/meson.build b/test cases/unit/101 relative find program/meson.build
index 5745d8a..5745d8a 100644
--- a/test cases/unit/99 relative find program/meson.build
+++ b/test cases/unit/101 relative find program/meson.build
diff --git a/test cases/unit/99 relative find program/subdir/meson.build b/test cases/unit/101 relative find program/subdir/meson.build
index 475f5f5..475f5f5 100644
--- a/test cases/unit/99 relative find program/subdir/meson.build
+++ b/test cases/unit/101 relative find program/subdir/meson.build
diff --git a/test cases/unit/100 rlib linkage/lib2.rs b/test cases/unit/102 rlib linkage/lib2.rs
index 3487bc5..3487bc5 100644
--- a/test cases/unit/100 rlib linkage/lib2.rs
+++ b/test cases/unit/102 rlib linkage/lib2.rs
diff --git a/test cases/unit/100 rlib linkage/main.rs b/test cases/unit/102 rlib linkage/main.rs
index d0f82e4..d0f82e4 100644
--- a/test cases/unit/100 rlib linkage/main.rs
+++ b/test cases/unit/102 rlib linkage/main.rs
diff --git a/test cases/unit/100 rlib linkage/meson.build b/test cases/unit/102 rlib linkage/meson.build
index 2d15b2a..2d15b2a 100644
--- a/test cases/unit/100 rlib linkage/meson.build
+++ b/test cases/unit/102 rlib linkage/meson.build
diff --git a/test cases/unit/101 python without pkgconfig/meson.build b/test cases/unit/103 python without pkgconfig/meson.build
index b3a0c42..b3a0c42 100644
--- a/test cases/unit/101 python without pkgconfig/meson.build
+++ b/test cases/unit/103 python without pkgconfig/meson.build
diff --git a/test cases/unit/97 link full name/.gitignore b/test cases/unit/98 link full name/.gitignore
index 8129601..8129601 100644
--- a/test cases/unit/97 link full name/.gitignore
+++ b/test cases/unit/98 link full name/.gitignore
diff --git a/test cases/unit/97 link full name/libtestprovider/meson.build b/test cases/unit/98 link full name/libtestprovider/meson.build
index 128c213..128c213 100644
--- a/test cases/unit/97 link full name/libtestprovider/meson.build
+++ b/test cases/unit/98 link full name/libtestprovider/meson.build
diff --git a/test cases/unit/97 link full name/libtestprovider/provider.c b/test cases/unit/98 link full name/libtestprovider/provider.c
index 5e79966..5e79966 100644
--- a/test cases/unit/97 link full name/libtestprovider/provider.c
+++ b/test cases/unit/98 link full name/libtestprovider/provider.c
diff --git a/test cases/unit/97 link full name/proguser/meson.build b/test cases/unit/98 link full name/proguser/meson.build
index 5be5bc9..5be5bc9 100644
--- a/test cases/unit/97 link full name/proguser/meson.build
+++ b/test cases/unit/98 link full name/proguser/meson.build
diff --git a/test cases/unit/97 link full name/proguser/receiver.c b/test cases/unit/98 link full name/proguser/receiver.c
index 65e9d8e..65e9d8e 100644
--- a/test cases/unit/97 link full name/proguser/receiver.c
+++ b/test cases/unit/98 link full name/proguser/receiver.c
diff --git a/test cases/unit/98 install all targets/foo1-devel.h b/test cases/unit/99 install all targets/bar-custom.txt
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/foo1-devel.h
+++ b/test cases/unit/99 install all targets/bar-custom.txt
diff --git a/test cases/unit/98 install all targets/subdir/bar2-devel.h b/test cases/unit/99 install all targets/bar-devel.h
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/subdir/bar2-devel.h
+++ b/test cases/unit/99 install all targets/bar-devel.h
diff --git a/test cases/unit/98 install all targets/subdir/foo2.in b/test cases/unit/99 install all targets/bar-notag.txt
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/subdir/foo2.in
+++ b/test cases/unit/99 install all targets/bar-notag.txt
diff --git a/test cases/unit/98 install all targets/custom_files/data.txt b/test cases/unit/99 install all targets/custom_files/data.txt
index 557db03..557db03 100644
--- a/test cases/unit/98 install all targets/custom_files/data.txt
+++ b/test cases/unit/99 install all targets/custom_files/data.txt
diff --git a/test cases/unit/98 install all targets/subdir/foo3-devel.h b/test cases/unit/99 install all targets/foo.in
index e69de29..e69de29 100644
--- a/test cases/unit/98 install all targets/subdir/foo3-devel.h
+++ b/test cases/unit/99 install all targets/foo.in
diff --git a/test cases/unit/99 install all targets/foo1-devel.h b/test cases/unit/99 install all targets/foo1-devel.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/unit/99 install all targets/foo1-devel.h
diff --git a/test cases/unit/98 install all targets/lib.c b/test cases/unit/99 install all targets/lib.c
index 2ea9c7d..2ea9c7d 100644
--- a/test cases/unit/98 install all targets/lib.c
+++ b/test cases/unit/99 install all targets/lib.c
diff --git a/test cases/unit/98 install all targets/main.c b/test cases/unit/99 install all targets/main.c
index 0fb4389..0fb4389 100644
--- a/test cases/unit/98 install all targets/main.c
+++ b/test cases/unit/99 install all targets/main.c
diff --git a/test cases/unit/98 install all targets/meson.build b/test cases/unit/99 install all targets/meson.build
index 94bd1fe..94bd1fe 100644
--- a/test cases/unit/98 install all targets/meson.build
+++ b/test cases/unit/99 install all targets/meson.build
diff --git a/test cases/unit/98 install all targets/script.py b/test cases/unit/99 install all targets/script.py
index c5f3be9..c5f3be9 100644
--- a/test cases/unit/98 install all targets/script.py
+++ b/test cases/unit/99 install all targets/script.py
diff --git a/test cases/unit/99 install all targets/subdir/bar2-devel.h b/test cases/unit/99 install all targets/subdir/bar2-devel.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/unit/99 install all targets/subdir/bar2-devel.h
diff --git a/test cases/unit/99 install all targets/subdir/foo2.in b/test cases/unit/99 install all targets/subdir/foo2.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/unit/99 install all targets/subdir/foo2.in
diff --git a/test cases/unit/99 install all targets/subdir/foo3-devel.h b/test cases/unit/99 install all targets/subdir/foo3-devel.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/unit/99 install all targets/subdir/foo3-devel.h
diff --git a/test cases/unit/98 install all targets/subdir/lib.c b/test cases/unit/99 install all targets/subdir/lib.c
index 2ea9c7d..2ea9c7d 100644
--- a/test cases/unit/98 install all targets/subdir/lib.c
+++ b/test cases/unit/99 install all targets/subdir/lib.c
diff --git a/test cases/unit/98 install all targets/subdir/main.c b/test cases/unit/99 install all targets/subdir/main.c
index 0fb4389..0fb4389 100644
--- a/test cases/unit/98 install all targets/subdir/main.c
+++ b/test cases/unit/99 install all targets/subdir/main.c
diff --git a/test cases/unit/98 install all targets/subdir/meson.build b/test cases/unit/99 install all targets/subdir/meson.build
index 53c796a..53c796a 100644
--- a/test cases/unit/98 install all targets/subdir/meson.build
+++ b/test cases/unit/99 install all targets/subdir/meson.build
diff --git a/test cases/unit/98 install all targets/subdir/script.py b/test cases/unit/99 install all targets/subdir/script.py
index c5f3be9..c5f3be9 100644
--- a/test cases/unit/98 install all targets/subdir/script.py
+++ b/test cases/unit/99 install all targets/subdir/script.py
diff --git a/test cases/vala/11 generated vapi/libfoo/foo.metadata b/test cases/vala/11 generated vapi/libfoo/foo.metadata
new file mode 100644
index 0000000..e208fe3
--- /dev/null
+++ b/test cases/vala/11 generated vapi/libfoo/foo.metadata
@@ -0,0 +1 @@
+Foo.bar nullable
diff --git a/test cases/vala/11 generated vapi/libfoo/meson.build b/test cases/vala/11 generated vapi/libfoo/meson.build
index 9dc14ce..ee425f2 100644
--- a/test cases/vala/11 generated vapi/libfoo/meson.build
+++ b/test cases/vala/11 generated vapi/libfoo/meson.build
@@ -24,7 +24,14 @@ libfoo_gir = gnome.generate_gir(libfoo,
],
)
+configure_file(
+ input: 'foo.metadata',
+ output: 'Foo-@0@.metadata'.format(libfoo_api_ver),
+ copy: true
+)
+
libfoo_vapi = gnome.generate_vapi('foo-' + libfoo_api_ver,
+ metadata_dirs: meson.current_build_dir(),
sources: libfoo_gir[0],
install: true,
)
diff --git a/tools/dircondenser.py b/tools/dircondenser.py
index 2a726df..fa299e9 100755
--- a/tools/dircondenser.py
+++ b/tools/dircondenser.py
@@ -81,6 +81,8 @@ def condense(dirname: str) -> None:
os.chdir(curdir)
replace_source('run_unittests.py', replacements)
replace_source('run_project_tests.py', replacements)
+ for f in glob('unittests/*.py'):
+ replace_source(f, replacements)
if __name__ == '__main__':
if len(sys.argv) != 1:
diff --git a/tools/gen_data.py b/tools/gen_data.py
deleted file mode 100755
index b1c62e0..0000000
--- a/tools/gen_data.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2020 Daniel Mensinger
-
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-
-# http://www.apache.org/licenses/LICENSE-2.0
-
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import sys
-import hashlib
-import textwrap
-import re
-from pathlib import Path
-from datetime import datetime
-import typing as T
-
-class DataFile:
- file_counter = 0
-
- def __init__(self, path: Path, root: Path):
- self.path = path
- self.id = self.path.relative_to(root)
- self.data_str = f'file_{DataFile.file_counter}_data_' + re.sub('[^a-zA-Z0-9]', '_', self.path.name)
- DataFile.file_counter += 1
-
- b = self.path.read_bytes()
- self.data = b.decode()
- self.sha256sum = hashlib.sha256(b).hexdigest()
-
- def __repr__(self) -> str:
- return f'<{type(self).__name__}: [{self.sha256sum}] {self.id}>'
-
-def main() -> int:
- root_dir = Path(__file__).resolve().parents[1]
- mesonbuild_dir = root_dir / 'mesonbuild'
- out_file = mesonbuild_dir / 'mesondata.py'
-
- data_dirs = sorted(mesonbuild_dir.glob('**/data'))
-
- data_files: T.List[DataFile] = []
-
- for d in data_dirs:
- for p in sorted(d.iterdir()):
- data_files += [DataFile(p, mesonbuild_dir)]
-
- print(f'Found {len(data_files)} data files')
-
- # Generate the data script
- data = ''
-
- data += textwrap.dedent(f'''\
- # Copyright {datetime.today().year} The Meson development team
-
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
-
- # http://www.apache.org/licenses/LICENSE-2.0
-
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
-
-
- ####
- #### WARNING: This is an automatically generated file! Do not edit!
- #### Generated by {Path(__file__).resolve().relative_to(root_dir)}
- ####
-
-
- # TODO: Remember to remove this also from tools/gen_data.py
- from pathlib import Path
- import typing as T
-
- if T.TYPE_CHECKING:
- from .environment import Environment
-
- ######################
- # BEGIN Data section #
- ######################
-
- ''')
-
- for i in data_files:
- data += f"{i.data_str} = '''\\\n{i.data}'''\n\n"
-
- data += textwrap.dedent(f'''
- ####################
- # END Data section #
- ####################
-
- class DataFile:
- def __init__(self, path: Path, sha256sum: str, data: str) -> None:
- self.path = path
- self.sha256sum = sha256sum
- self.data = data
-
- def write_once(self, path: Path) -> None:
- if not path.exists():
- path.write_text(self.data, encoding='utf-8')
-
- def write_to_private(self, env: 'Environment') -> Path:
- out_file = Path(env.scratch_dir) / 'data' / self.path.name
- out_file.parent.mkdir(exist_ok=True)
- self.write_once(out_file)
- return out_file
-
-
- mesondata = {{
- ''')
-
- for i in data_files:
- data += textwrap.indent(textwrap.dedent(f"""\
- '{i.id}': DataFile(
- Path('{i.id}'),
- '{i.sha256sum}',
- {i.data_str},
- ),
- """), ' ')
-
- data += textwrap.dedent('''\
- }
- ''')
-
- print(f'Updating {out_file}')
- out_file.write_text(data, encoding='utf-8')
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index daa1385..51ca7a0 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -1592,10 +1592,10 @@ class AllPlatformTests(BasePlatformTests):
os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
env = get_fake_env(testdir, self.builddir, self.prefix)
kwargs = {'required': True, 'silent': True}
- foo_dep = PkgConfigDependency('libfoo', env, kwargs)
+ foo_dep = PkgConfigDependency('libanswer', env, kwargs)
# Ensure link_args are properly quoted
libdir = PurePath(prefix) / PurePath(libdir)
- link_args = ['-L' + libdir.as_posix(), '-lfoo']
+ link_args = ['-L' + libdir.as_posix(), '-lanswer']
self.assertEqual(foo_dep.get_link_args(), link_args)
# Ensure include args are properly quoted
incdir = PurePath(prefix) / PurePath('include')
@@ -2306,7 +2306,6 @@ class AllPlatformTests(BasePlatformTests):
self.assertEqual(f.read().strip(), b'/* #undef FOO_BAR */')
with open(os.path.join(self.builddir, 'nosubst-nocopy2.txt'), 'rb') as f:
self.assertEqual(f.read().strip(), b'')
- self.assertRegex(out, r"DEPRECATION:.*\['array'\] is invalid.*dict")
def test_dirs(self):
with tempfile.TemporaryDirectory() as containing:
@@ -3186,11 +3185,6 @@ class AllPlatformTests(BasePlatformTests):
expected_lines = expected.split('\n')[1:]
out_start = out.find(expected_lines[0])
out_lines = out[out_start:].split('\n')[:len(expected_lines)]
- if sys.version_info < (3, 7, 0):
- # Dictionary order is not stable in Python <3.7, so sort the lines
- # while comparing
- expected_lines = sorted(expected_lines)
- out_lines = sorted(out_lines)
for e, o in zip(expected_lines, out_lines):
if e.startswith(' external dep'):
self.assertRegex(o, r'^ external dep : (YES [0-9.]*|NO)$')
@@ -3830,7 +3824,7 @@ class AllPlatformTests(BasePlatformTests):
self.assertEqual(sorted(link_args), sorted(['-flto']))
def test_install_tag(self) -> None:
- testdir = os.path.join(self.unit_test_dir, '98 install all targets')
+ testdir = os.path.join(self.unit_test_dir, '99 install all targets')
self.init(testdir)
self.build()
@@ -3952,7 +3946,7 @@ class AllPlatformTests(BasePlatformTests):
do_install(None, expected_all, 2)
def test_introspect_install_plan(self):
- testdir = os.path.join(self.unit_test_dir, '98 install all targets')
+ testdir = os.path.join(self.unit_test_dir, '99 install all targets')
introfile = os.path.join(self.builddir, 'meson-info', 'intro-install_plan.json')
self.init(testdir)
self.assertPathExists(introfile)
@@ -4139,7 +4133,7 @@ class AllPlatformTests(BasePlatformTests):
}}
''')
- testdir = os.path.join(self.unit_test_dir, '100 rlib linkage')
+ testdir = os.path.join(self.unit_test_dir, '102 rlib linkage')
gen_file = os.path.join(testdir, 'lib.rs')
with open(gen_file, 'w') as f:
f.write(template.format(0))
@@ -4159,7 +4153,7 @@ class AllPlatformTests(BasePlatformTests):
self.assertIn('exit status 39', cm.exception.stdout)
def test_custom_target_name(self):
- testdir = os.path.join(self.unit_test_dir, '99 custom target name')
+ testdir = os.path.join(self.unit_test_dir, '100 custom target name')
self.init(testdir)
out = self.build()
if self.backend is Backend.ninja:
diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py
index bd2f902..cfc78ce 100644
--- a/unittests/baseplatformtests.py
+++ b/unittests/baseplatformtests.py
@@ -160,7 +160,7 @@ class BasePlatformTests(TestCase):
p = subprocess.run(command, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, env=env,
encoding='utf-8',
- universal_newlines=True, cwd=workdir, timeout=60 * 5)
+ text=True, cwd=workdir, timeout=60 * 5)
print(p.stdout)
if p.returncode != 0:
if 'MESON_SKIP_TEST' in p.stdout:
@@ -249,10 +249,10 @@ class BasePlatformTests(TestCase):
def run_tests(self, *, inprocess=False, override_envvars=None):
if not inprocess:
- self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars)
+ return self._run(self.test_command, workdir=self.builddir, override_envvars=override_envvars)
else:
with mock.patch.dict(os.environ, override_envvars):
- run_mtest_inprocess(['-C', self.builddir])
+ return run_mtest_inprocess(['-C', self.builddir])[1]
def install(self, *, use_destdir=True, override_envvars=None):
if self.backend is not Backend.ninja:
@@ -263,7 +263,7 @@ class BasePlatformTests(TestCase):
override_envvars = destdir
else:
override_envvars.update(destdir)
- self._run(self.install_command, workdir=self.builddir, override_envvars=override_envvars)
+ return self._run(self.install_command, workdir=self.builddir, override_envvars=override_envvars)
def uninstall(self, *, override_envvars=None):
self._run(self.uninstall_command, workdir=self.builddir, override_envvars=override_envvars)
diff --git a/unittests/datatests.py b/unittests/datatests.py
index e440243..b623f1f 100644
--- a/unittests/datatests.py
+++ b/unittests/datatests.py
@@ -13,12 +13,9 @@
# limitations under the License.
import re
-import textwrap
import unittest
-import hashlib
from itertools import chain
from pathlib import Path
-import typing as T
import mesonbuild.mlog
import mesonbuild.depfile
@@ -237,36 +234,3 @@ class DataTests(unittest.TestCase):
interp = Interpreter(FakeBuild(env), mock=True)
astint = AstInterpreter('.', '', '')
self.assertEqual(set(interp.funcs.keys()), set(astint.funcs.keys()))
-
- def test_mesondata_is_up_to_date(self):
- from mesonbuild.mesondata import mesondata
- err_msg = textwrap.dedent('''
-
- ###########################################################
- ### mesonbuild.mesondata is not up-to-date ###
- ### Please regenerate it by running tools/gen_data.py ###
- ###########################################################
-
- ''')
-
- root_dir = Path(__file__).parents[1]
-
- mesonbuild_dir = root_dir / 'mesonbuild'
-
- data_dirs = mesonbuild_dir.glob('**/data')
- data_files = [] # type: T.List[T.Tuple(str, str)]
-
- for i in data_dirs:
- for p in i.iterdir():
- data_files += [(p.relative_to(mesonbuild_dir).as_posix(), hashlib.sha256(p.read_bytes()).hexdigest())]
-
- current_files = set(mesondata.keys())
- scanned_files = {x[0] for x in data_files}
-
- self.assertSetEqual(current_files, scanned_files, err_msg + 'Data files were added or removed\n')
- errors = []
- for i in data_files:
- if mesondata[i[0]].sha256sum != i[1]:
- errors += [i[0]]
-
- self.assertListEqual(errors, [], err_msg + 'Files were changed')
diff --git a/unittests/helpers.py b/unittests/helpers.py
index b759dba..bf06bdc 100644
--- a/unittests/helpers.py
+++ b/unittests/helpers.py
@@ -5,11 +5,13 @@ import unittest
import functools
import re
import typing as T
+from pathlib import Path
from contextlib import contextmanager
from mesonbuild.compilers import detect_c_compiler, compiler_from_language
from mesonbuild.mesonlib import (
- MachineChoice, is_osx, is_cygwin, EnvironmentException, OptionKey, MachineChoice
+ MachineChoice, is_osx, is_cygwin, EnvironmentException, OptionKey, MachineChoice,
+ OrderedSet
)
from run_tests import get_fake_env
@@ -170,3 +172,15 @@ def get_rpath(fname: str) -> T.Optional[str]:
# don't check for, so clear those
final = ':'.join([e for e in raw.split(':') if not e.startswith('/nix')])
return final
+
+def get_path_without_cmd(cmd: str, path: str) -> str:
+ pathsep = os.pathsep
+ paths = OrderedSet([Path(p).resolve() for p in path.split(pathsep)])
+ while True:
+ full_path = shutil.which(cmd, path=path)
+ if full_path is None:
+ break
+ dirname = Path(full_path).resolve().parent
+ paths.discard(dirname)
+ path = pathsep.join([str(p) for p in paths])
+ return path
diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py
index 8ff0f8e..90db4ca 100644
--- a/unittests/linuxliketests.py
+++ b/unittests/linuxliketests.py
@@ -148,18 +148,18 @@ class LinuxlikeTests(BasePlatformTests):
self.assertTrue(foo_dep.found())
self.assertEqual(foo_dep.get_version(), '1.0')
self.assertIn('-lfoo', foo_dep.get_link_args())
- self.assertEqual(foo_dep.get_pkgconfig_variable('foo', {}), 'bar')
- self.assertPathEqual(foo_dep.get_pkgconfig_variable('datadir', {}), '/usr/data')
+ self.assertEqual(foo_dep.get_pkgconfig_variable('foo', [], None), 'bar')
+ self.assertPathEqual(foo_dep.get_pkgconfig_variable('datadir', [], None), '/usr/data')
libhello_nolib = PkgConfigDependency('libhello_nolib', env, kwargs)
self.assertTrue(libhello_nolib.found())
self.assertEqual(libhello_nolib.get_link_args(), [])
self.assertEqual(libhello_nolib.get_compile_args(), [])
- self.assertEqual(libhello_nolib.get_pkgconfig_variable('foo', {}), 'bar')
- self.assertEqual(libhello_nolib.get_pkgconfig_variable('prefix', {}), self.prefix)
+ self.assertEqual(libhello_nolib.get_pkgconfig_variable('foo', [], None), 'bar')
+ self.assertEqual(libhello_nolib.get_pkgconfig_variable('prefix', [], None), self.prefix)
if version_compare(libhello_nolib.check_pkgconfig(libhello_nolib.pkgbin),">=0.29.1"):
- self.assertEqual(libhello_nolib.get_pkgconfig_variable('escaped_var', {}), r'hello\ world')
- self.assertEqual(libhello_nolib.get_pkgconfig_variable('unescaped_var', {}), 'hello world')
+ self.assertEqual(libhello_nolib.get_pkgconfig_variable('escaped_var', [], None), r'hello\ world')
+ self.assertEqual(libhello_nolib.get_pkgconfig_variable('unescaped_var', [], None), 'hello world')
cc = detect_c_compiler(env, MachineChoice.HOST)
if cc.get_id() in {'gcc', 'clang'}:
@@ -1334,7 +1334,7 @@ class LinuxlikeTests(BasePlatformTests):
see: https://github.com/mesonbuild/meson/issues/9000
https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a
'''
- testdir = os.path.join(self.unit_test_dir, '97 link full name','libtestprovider')
+ testdir = os.path.join(self.unit_test_dir, '98 link full name','libtestprovider')
oldprefix = self.prefix
# install into installdir without using DESTDIR
installdir = self.installdir
@@ -1347,7 +1347,7 @@ class LinuxlikeTests(BasePlatformTests):
self.new_builddir()
env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir),
'PKG_CONFIG_PATH': os.path.join(installdir, self.libdir, 'pkgconfig')}
- testdir = os.path.join(self.unit_test_dir, '97 link full name','proguser')
+ testdir = os.path.join(self.unit_test_dir, '98 link full name','proguser')
self.init(testdir,override_envvars=env)
# test for link with full path
@@ -1717,7 +1717,7 @@ class LinuxlikeTests(BasePlatformTests):
p = subprocess.run([ar, 't', outlib],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
- universal_newlines=True, timeout=1)
+ text=True, timeout=1)
obj_files = p.stdout.strip().split('\n')
self.assertEqual(len(obj_files), 1)
self.assertTrue(obj_files[0].endswith('-prelink.o'))
diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py
index 25f3b1a..c5e5233 100644
--- a/unittests/platformagnostictests.py
+++ b/unittests/platformagnostictests.py
@@ -32,7 +32,7 @@ class PlatformAgnosticTests(BasePlatformTests):
Tests that find_program() with a relative path does not find the program
in current workdir.
'''
- testdir = os.path.join(self.unit_test_dir, '99 relative find program')
+ testdir = os.path.join(self.unit_test_dir, '101 relative find program')
self.init(testdir, workdir=testdir)
def test_invalid_option_names(self):
@@ -68,5 +68,5 @@ class PlatformAgnosticTests(BasePlatformTests):
interp.process(fname)
def test_python_dependency_without_pkgconfig(self):
- testdir = os.path.join(self.unit_test_dir, '101 python without pkgconfig')
+ testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig')
self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'})
diff --git a/unittests/rewritetests.py b/unittests/rewritetests.py
index 1e6a398..161ae9d 100644
--- a/unittests/rewritetests.py
+++ b/unittests/rewritetests.py
@@ -32,8 +32,7 @@ class RewriterTests(BasePlatformTests):
if isinstance(args, str):
args = [args]
command = self.rewrite_command + ['--verbose', '--skip', '--sourcedir', directory] + args
- p = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- universal_newlines=True, timeout=60)
+ p = subprocess.run(command, capture_output=True, text=True, timeout=60)
print('STDOUT:')
print(p.stdout)
print('STDERR:')
diff --git a/unittests/windowstests.py b/unittests/windowstests.py
index bd75c74..d3ad932 100644
--- a/unittests/windowstests.py
+++ b/unittests/windowstests.py
@@ -373,3 +373,29 @@ class WindowsTests(BasePlatformTests):
raise SkipTest('Not using MSVC')
self.init(testdir, extra_args=['-Dtest-failure=true'])
self.assertRaises(subprocess.CalledProcessError, self.build)
+
+ @unittest.skipIf(is_cygwin(), "Needs visual studio")
+ def test_vsenv_option(self):
+ if self.backend is not Backend.ninja:
+ raise SkipTest('Only ninja backend is valid for test')
+ env = os.environ.copy()
+ env['MESON_FORCE_VSENV_FOR_UNITTEST'] = '1'
+ # Remove ninja from PATH to ensure that the one provided by Visual
+ # Studio is picked, as a regression test for
+ # https://github.com/mesonbuild/meson/issues/9774
+ env['PATH'] = get_path_without_cmd('ninja', env['PATH'])
+ testdir = os.path.join(self.common_test_dir, '1 trivial')
+ out = self.init(testdir, extra_args=['--vsenv'], override_envvars=env)
+ self.assertIn('Activating VS', out)
+ self.assertRegex(out, 'Visual Studio environment is needed to run Ninja')
+ # All these directly call ninja with the full path, so we need to patch
+ # it out to use meson subcommands
+ with mock.patch.object(self, 'build_command', self.meson_command + ['compile']):
+ out = self.build(override_envvars=env)
+ self.assertIn('Activating VS', out)
+ with mock.patch.object(self, 'test_command', self.meson_command + ['test']):
+ out = self.run_tests(override_envvars=env)
+ self.assertIn('Activating VS', out)
+ with mock.patch.object(self, 'install_command', self.meson_command + ['install']):
+ out = self.install(override_envvars=env)
+ self.assertIn('Activating VS', out)